﻿// ----------------------------------------------------------------------
// <author name="Moses Kehengu"/>
// <copyright file="Utilities.cs" company="Futures Group International">
//     Copyright statement. All right reserved
// </copyright>
//
// ------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Net.Mail;
using System.Net;
using System.Data.Common;
using System.Data;
using System.Xml;
using System.Configuration;
using System.Data.SqlClient;
using System.Data.OleDb;
using DTS = Microsoft.SqlServer.Dts.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using DataModels.Common;
using DataModels.Enumerations;
using GenericTools.ReportProcessing;
using System.Linq;

namespace GenericTools
{
    /// <summary>
    /// Contains methods of commonly repeated operations
    /// </summary>
    public partial class Utilities : GenericTools.Models.BaseWebAuthorization
    {
        #region Class Constants
        private static int m_MINIMUM_DATA_COMPONENTS = 4;  // facility code, period, month and data
        private static int m_MAXIMUM_REPVERSION = 5;

        public const string SETTING_TEMPLATE_CACHEDB_NAME = "CacheDBName";
        public const string SETTING_CACHEDB_STATUS = "CacheDBStatus";
        public const string SETTING_CACHEDB_CREATE_DATE = "CacheDBCreateDate";
        public const string SETTING_CACHEDB_CUT_OFF_POINT = "CacheDBCutOffPoint";

        public const string CACHEDB_STATUS_CREATING = "CREATING";
        public const string CACHEDB_STATUS_READY = "READY";
        public const string CACHEDB_STATUS_ERROR = "ERROR";

        public const int ACCESS_LEVELS_ADMINISTRATOR_ID = 1;
        public const int ACCESS_LEVELS_NATION_ID = 2;
        public const int ACCESS_LEVELS_REGION_ID = 3;
        public const int ACCESS_LEVELS_DISTRICT_ID = 4;
        public const int ACCESS_LEVELS_FACILITY_ID = 5;
        #endregion

        #region Class Variables
        private static string logFilename = "iqsms";
        private static int MAX_LOG_FILESIZE = 5242880;    //5 MB
        private static string from;
        private static string to;
        private static string subject;
        private static string body;

        #region Data Cache
        private static DataTable cache_ExpectedReports;
        private static DataTable cache_ExpectedReportViews;
        private static DataTable cache_AllFacilities;
        private static DataTable cache_FacilitiesDetails;
        private static DataTable cache_AllDistricts;
        private static DataTable cache_AllRegions;
        private static DataTable cache_RegisteredUsers;
        private static DataTable cache_AssistanceAssignedAllRegions;
        private static DataTable cache_AssistanceAssignedAllDistricts;
        private static DataTable cache_AssistanceAssignedAllFacilities;

        private static Dictionary<string, DataTable> cache_FacilitiesAssignedUsers;
        private static Dictionary<int, DataTable> cache_DistrictsAssignedUsers;
        private static Dictionary<int, DataTable> cache_RegionsAssignedUsers;
        
        private static DataTable cache_AllReportYears;
        private static DataTable cache_AllReportPeriods;

        private static DataTable cache_BlockedReports;

        private static DataTable cache_ExpectedCharts;

        private static DataTable AllComparisons;

        private static Dictionary<int, bool> cache_ReportsCanBeDeleted;

        private static Dictionary<int, string> cache_RegionNames;
        private static Dictionary<int, string> cache_RegionNamesFromDistrictID;
        private static Dictionary<int, string> cache_DistrictNames;

        private static Dictionary<string, DataTable> cache_FacilityDetails;
        private static Dictionary<int, DataTable> cache_ReportDataDescriptions;
        private static Dictionary<int, DataTable> cache_ReportDetails;
        private static Dictionary<int, DataTable> cache_DistrictDetails;
        private static Dictionary<int, DataTable> cache_RegionDetails;
        
        private static Dictionary<int, DataTable> cache_DistrictByRegionID;
        private static Dictionary<int, DataTable> cache_FacilitiesByRegionID;
        
        private static Dictionary<int, DataTable> cache_FacilitiesByDistrictID;
        private static Dictionary<int, DataTable> cache_BasicInfoFacilitiesByDistrictID;

        private static Dictionary<string, DataTable> cache_FacilityDistrict;
        private static Dictionary<string, DataTable> cache_FacilityRegion;
        private static Dictionary<int, DataTable> cache_DistrictRegion;

        private static Dictionary<int, DataTable> cache_ChartIndicators;
        private static Dictionary<string, DataTable> cache_ExpectedFacilityReports;
        private static Dictionary<string, DataTable> cache_RegisteredReportingUsers;
        private static Dictionary<int, DataTable> cache_RegisteredUserContacts;
        private static Dictionary<int, DataTable> cache_AllLanguageTranslations;

        private static Dictionary<int, DataTable> cache_AssistanceAssignedRegions;
        private static Dictionary<int, DataTable> cache_AssistanceSelectedUserAssignedRegions;
        private static Dictionary<int, DataTable> cache_AssistanceAssignedDistricts;
        private static Dictionary<int, DataTable> cache_AssistanceSelectedUserAssignedDistricts;
        private static Dictionary<int, DataTable> cache_AssistanceAssignedFacilities;
        private static Dictionary<int, DataTable> cache_AssistanceSelectedUserAssignedFacilities;

        private static Dictionary<int, DataTable> cache_ReportDataLocations;
        private static Dictionary<int, DataTable> cache_ReportRules;

        private static Dictionary<int, DataTable> cache_AllFacilitiesByDistrict = null;
        private static Dictionary<int, DataTable> cache_AllFacilitiesByRegion = null;

        private static DataTable cache_AllUsers;
        private static DataTable cache_FacilityTypes;

        // language, id, data
        private static Dictionary<int, Dictionary<int, DataTable>> cache_LanguageTranslationByLabelNo;        
        #endregion

        private static IQServices.IQService webService;
        #endregion

        #region Constructors
        static Utilities()
        {
            logFilename = AppConfiguration.ApplicationName;

            cache_ExpectedReports = null;
            cache_ExpectedReportViews = null;
            cache_AllFacilities = null;
            cache_AllDistricts = null;
            cache_AllRegions = null;
            cache_RegisteredUsers = null;

            cache_AssistanceAssignedAllRegions = null;
            cache_AssistanceAssignedAllDistricts = null;
            cache_AssistanceAssignedAllFacilities = null;

            cache_BlockedReports = null;
            cache_AllReportYears = null;
            cache_AllReportPeriods = null;

            cache_ExpectedCharts = null;

            AllComparisons = null;

            cache_FacilitiesAssignedUsers = new Dictionary<string,DataTable>();
            cache_DistrictsAssignedUsers = new Dictionary<int,DataTable>();
            cache_RegionsAssignedUsers = new Dictionary<int,DataTable>();

            cache_ReportsCanBeDeleted = new Dictionary<int, bool>();

            cache_RegionNames = new Dictionary<int, string>();
            cache_RegionNamesFromDistrictID = new Dictionary<int, string>();
            cache_DistrictNames = new Dictionary<int, string>();

            cache_FacilityDetails = new Dictionary<string, DataTable>();
            cache_ReportDataDescriptions = new Dictionary<int, DataTable>();
            cache_ReportDetails = new Dictionary<int, DataTable>();
            cache_DistrictDetails = new Dictionary<int, DataTable>();
            cache_RegionDetails = new Dictionary<int, DataTable>();
            
            cache_DistrictByRegionID = new Dictionary<int, DataTable>();
            cache_FacilitiesByRegionID = new Dictionary<int, DataTable>();
            cache_FacilitiesByDistrictID = new Dictionary<int, DataTable>();
            cache_BasicInfoFacilitiesByDistrictID = new Dictionary<int, DataTable>();
            
            cache_ChartIndicators = new Dictionary<int, DataTable>();
            cache_ExpectedFacilityReports = new Dictionary<string, DataTable>();
            
            cache_RegisteredReportingUsers = new Dictionary<string, DataTable>();
            cache_RegisteredUserContacts = new Dictionary<int, DataTable>();
            
            cache_AllLanguageTranslations = new Dictionary<int, DataTable>();
            cache_LanguageTranslationByLabelNo = new Dictionary<int, Dictionary<int, DataTable>>();

            cache_AssistanceAssignedRegions = new Dictionary<int, DataTable>();
            cache_AssistanceSelectedUserAssignedRegions = new Dictionary<int, DataTable>();
            cache_AssistanceAssignedDistricts = new Dictionary<int, DataTable>();
            cache_AssistanceSelectedUserAssignedDistricts = new Dictionary<int, DataTable>();
            cache_AssistanceAssignedFacilities = new Dictionary<int, DataTable>();
            cache_AssistanceSelectedUserAssignedFacilities = new Dictionary<int, DataTable>();

            cache_FacilityRegion = new Dictionary<string, DataTable>();
            cache_FacilityDistrict = new Dictionary<string, DataTable>();
            cache_DistrictRegion = new Dictionary<int, DataTable>();

            cache_ReportDataLocations = new Dictionary<int, DataTable>();
            cache_ReportRules = new Dictionary<int, DataTable>();

            cache_AllFacilitiesByDistrict = new Dictionary<int, DataTable>();
            cache_AllFacilitiesByRegion = new Dictionary<int, DataTable>();

            cache_AllUsers = null;
            cache_FacilityTypes = null;

            webService = new IQServices.IQService();
            webService.Url = AppConfiguration.WebServiceURL;

            //if (AppConfiguration.AccessMethod == DataAccessMethod.WEB_SERVICES)
            //{
            //    webService = new IQServices.IQService();
            //    webService.Url = AppConfiguration.WebServiceURL;
            //}
        }
        #endregion

        #region Error Logging
        /// <summary>
        /// Logs the exception into the logfile and e-mailing it to developer
        /// </summary>
        /// <param name="ex"></param>
        public static void LogError(Exception ex, DbCommand command)
        {
            string error = CreateLogEntry(ex, command);
            WriteLog(error);

            if (AppConfiguration.EnableErrorLogMail)
            {
                string from = AppConfiguration.MailFrom;
                string to = AppConfiguration.ErrorLogEmailAddress;
                string subject = String.Format("{0} - Error", AppConfiguration.ApplicationName);
                string body = error;
                SendMail(from, to, subject, body);
            }
        }

        /// <summary>
        /// Creates a detailed log entry from the exceptio object
        /// </summary>
        /// <param name="ex">Exception</param>
        /// <returns></returns>
        public static string CreateLogEntry(Exception ex, DbCommand command)
        {
            string dateTime = DateTime.Now.ToLongDateString() + ", at " + DateTime.Now.ToShortTimeString();
            StringBuilder errorMessage = new StringBuilder();
            errorMessage.Append("Exception generated on " + dateTime);
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append("Message: " + ex.Message);
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append("Source: " + ex.Source);
            if (ex.InnerException != null)
            {
                errorMessage.Append(Environment.NewLine);
                errorMessage.Append("Inner Message: " + ex.InnerException.Message);
                errorMessage.Append(Environment.NewLine);
                errorMessage.Append("Inner Source: " + ex.InnerException.Source);

                try
                {
                    SqlException sqlException = (SqlException)ex;
                    WriteSQLExceptionLogEntry(sqlException, errorMessage);
                }
                catch { }
            }

            try
            {
                SqlException sqlException = (SqlException)ex;
                WriteSQLExceptionLogEntry(sqlException, errorMessage);
            }
            catch { }

            errorMessage.Append(Environment.NewLine);
            errorMessage.Append("Beginning Stack Trace: ");
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append(ex.StackTrace);
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append("Ending Stack Trace");
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append(Environment.NewLine);

            if (command != null) WriteDbCommandLogEntry(command, errorMessage);

            return errorMessage.ToString();
        }

        /// <summary>
        /// Write contents into the hard disk log file
        /// </summary>
        /// <param name="contents">Contents of the log</param>
        public static void WriteLog(string contents)
        {
            try
            {
                string logFileDirectory = AppConfiguration.LogFileDirectory;
                if (!Directory.Exists(logFileDirectory)) Directory.CreateDirectory(logFileDirectory);
                string filename = logFileDirectory + @"\" + logFilename + ".log";
                if (!File.Exists(filename)) File.Create(filename).Close();

                FileInfo fileInfo = new FileInfo(filename);
                FileStream logFile = null;
                if (fileInfo.Length > MAX_LOG_FILESIZE)
                {
                    string date = DateTime.Now.ToLongDateString().Replace("/", "-");
                    string time = DateTime.Now.ToLongTimeString().Replace(":", "");
                    string oldLogFilename = logFilename + " [" + date + " " + time + "]" + ".log";
                    File.Move(filename, oldLogFilename);
                    logFile = new FileStream(filename, FileMode.Create);

                }
                else
                {
                    logFile = new FileStream(filename, FileMode.Append);
                }

                byte[] logContents = Encoding.UTF8.GetBytes(contents);
                logFile.Write(logContents, 0, logContents.Length);
                logFile.Flush();
                logFile.Close();
            }
            catch { }
        }

        public static void WriteSQLExceptionLogEntry(SqlException sqlException, StringBuilder errorMessage)
        {
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append("Sql Exception Details:");
            errorMessage.Append(Environment.NewLine);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append(".NET Framework Data Provider for SQL Server severity Level: ");
            errorMessage.Append(sqlException.Class);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append("HRESULT Error: ");
            errorMessage.Append(sqlException.ErrorCode);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append("Help link: ");
            errorMessage.Append(sqlException.HelpLink);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append("Method that throws exception: ");
            errorMessage.Append(sqlException.TargetSite);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append(Environment.NewLine);
            if (sqlException.Errors.Count > 0)
            {
                errorMessage.Append("Additional Error Information: ");
                errorMessage.Append(sqlException.Errors.Count);
                string er = (sqlException.Errors.Count == 1) ? " error" : " errors";
                errorMessage.Append(er);
                errorMessage.Append(Environment.NewLine);

                int count = 0;
                foreach (SqlError error in sqlException.Errors)
                {
                    errorMessage.Append("Details of Error :");
                    errorMessage.Append(++count);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Severity Level: ");
                    errorMessage.Append(error.Class);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Line number within Transact-SQL command: ");
                    errorMessage.Append(error.LineNumber);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Message: ");
                    errorMessage.Append(error.Message);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Error Type Number: ");
                    errorMessage.Append(error.Number);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Stored Procedure or RPC: ");
                    errorMessage.Append(error.Procedure);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("SQL Server instance name: ");
                    errorMessage.Append(error.Server);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Provider name: ");
                    errorMessage.Append(error.Source);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("SQL Server numeric code: ");
                    errorMessage.Append(error.State);
                    errorMessage.Append(Environment.NewLine);
                }
            }
        }

        public static void WriteDbCommandLogEntry(DbCommand command, StringBuilder errorMessage)
        {
            string state = (command.Connection.State == ConnectionState.Open) ? "Open" : "Not Open";
            errorMessage.Append("Connection State: ");
            errorMessage.Append(state);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append("Command Text: ");
            errorMessage.Append(command.CommandText);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append("Command Timeout: ");
            errorMessage.Append(command.CommandTimeout);
            errorMessage.Append(Environment.NewLine);

            string type = String.Empty;
            if (command.CommandType == CommandType.TableDirect) type = "Table";
            if (command.CommandType == CommandType.Text) type = "SQL Text Command";
            if (command.CommandType == CommandType.StoredProcedure) type = "Stored Procedure";
            errorMessage.Append("Command Type: ");
            errorMessage.Append(type);
            errorMessage.Append(Environment.NewLine);

            errorMessage.Append("Parameter Count: ");
            errorMessage.Append(command.Parameters.Count);
            errorMessage.Append(Environment.NewLine);

            if (command.Parameters.Count > 0)
            {
                int count = 0;
                foreach (DbParameter param in command.Parameters)
                {
                    errorMessage.Append("Parameter: ");
                    errorMessage.Append(++count);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Parameter Name: ");
                    errorMessage.Append(param.ParameterName);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Parameter Value: ");
                    string value = "NULL";
                    try { value = param.Value.ToString(); }
                    catch { }
                    errorMessage.Append(value);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Parameter DbType: ");
                    string dbType = "UNSPECIFIED OR OTHER TYPES";
                    try
                    {
                        if (param.DbType == DbType.Boolean) dbType = "Boolean";
                        if (param.DbType == DbType.DateTime) dbType = "DateTime";
                        if (param.DbType == DbType.Int32) dbType = "Integer";
                        if (param.DbType == DbType.String) dbType = "String";
                    }
                    catch { }
                    errorMessage.Append(dbType);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append("Parameter Size: ");
                    errorMessage.Append(param.Size);
                    errorMessage.Append(Environment.NewLine);

                    errorMessage.Append(Environment.NewLine);
                }
            }
        }
        #endregion

        #region Sending E-Mail Methods
        /// <summary>
        /// Sends email
        /// </summary>
        /// <param name="from">Source address</param>
        /// <param name="to">Destination address</param>
        /// <param name="subject">Subject</param>
        /// <param name="body">Body</param>
        public static void SendMail(string from, string to, string subject, string body)
        {
            Utilities.from = from;
            Utilities.to = to;
            Utilities.subject = subject;
            Utilities.body = body;

            Thread thread = new Thread(new ThreadStart(SendMail));
            thread.Start();
        }

        /// <summary>
        /// Sends e-mail. 
        /// </summary>
        /// <param name="to">Destination e-mail address</param>
        /// <param name="subject">Subject of e-mail</param>
        /// <param name="body">Body of e-mail</param>
        public static void SendMail(string to, string subject, string body)
        {
            SendMail(AppConfiguration.MailFrom, to, subject, body);
        }

        /// <summary>
        /// Actual sending of e-mail
        /// </summary>
        private static void SendMail()
        {
            try
            {
                NetworkCredential credential = new NetworkCredential();
                credential.UserName = AppConfiguration.MailUsername;
                credential.Password = AppConfiguration.MailPassword;

                SmtpClient client = new SmtpClient();
                client.Host = AppConfiguration.MailServer;
                client.Port = AppConfiguration.MailServerPort;
                client.UseDefaultCredentials = false;
                client.EnableSsl = true;
                client.Credentials = credential;

                MailMessage message = new MailMessage(from, to, subject, body);            
                client.Send(message);
            }
            catch (Exception ex)
            {
                string errorMessage = CreateLogEntry(ex, null);
                WriteLog(errorMessage);
            }
        }

        /// <summary>
        /// Sends e-mail. Throws exception
        /// </summary>
        /// <param name="to">Destination e-mail address</param>
        /// <param name="subject">E-mail subject</param>
        /// <param name="body">E-mail body</param>
        public static void SendMailSync(string to, string subject, string body)
        {
            NetworkCredential credential = new NetworkCredential();
            credential.UserName = AppConfiguration.MailUsername;
            credential.Password = AppConfiguration.MailPassword;

            SmtpClient client = new SmtpClient();
            client.Host = AppConfiguration.MailServer;
            client.Port = AppConfiguration.MailServerPort;
            client.UseDefaultCredentials = false;
            client.EnableSsl = true;
            client.Credentials = credential;

            MailMessage message = new MailMessage(AppConfiguration.MailFrom, to, subject, body);
            message.IsBodyHtml = true;
            try
            {
                client.Send(message);
            }
            catch (Exception ex)
            {
                string errorMessage = CreateLogEntry(ex, null);
                WriteLog(errorMessage);
                throw ex;
            }
        }
        #endregion

        #region PMTCT Report IDs
        /// <summary>
        /// Antenal Clinc
        /// </summary>
        public static int ANC_ID = 6;

        /// <summary>
        /// PMTCT Care Register
        /// </summary>
        public static int PCR_ID = 8;

        /// <summary>
        /// Maternity
        /// </summary>
        public static int MAT_ID = 7;

        /// <summary>
        /// Mother Child follow-up
        /// </summary>
        public static int MC_ID = 9;
        #endregion

        #region Location Methods
        public static string GetID(string name, ReportLevel reportLevel)
        {
            string id = String.Empty;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@ID";                           
                    param.DbType = DbType.String;
                    param.Size = 50;
                    param.Value = name;
                    command.Parameters.Add(param);
                    switch (reportLevel)
                    {
                        case ReportLevel.FACILITY:
                            command.CommandText = @"SELECT TOP(1) FacCode FROM Facilities WHERE FacName=@ID";
                            break;

                        case ReportLevel.DISTRICT:
                            command.CommandText = @"SELECT TOP(1) DistrictNo FROM District WHERE District=@ID";
                            break;

                        case ReportLevel.REGION:
                            command.CommandText = @"SELECT TOP(1) RegionNo FROM Region WHERE RegionName=@ID";
                            break;
                    }
                    id = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    IQServices.ReportLevel rLevel = IQServices.ReportLevel.NATION;
                    if (reportLevel == ReportLevel.REGION) rLevel = IQServices.ReportLevel.REGION;
                    if (reportLevel == ReportLevel.DISTRICT) rLevel = IQServices.ReportLevel.DISTRICT;
                    if (reportLevel == ReportLevel.FACILITY) rLevel = IQServices.ReportLevel.FACILITY;
                    string output = webService.GetID(name, rLevel);
                    id = DataTransformation.Decrypt(output);
                    break;
            }
            return id;
        }

        /// <summary>
        /// Gets the name of district identified by district ID districtID
        /// </summary>
        /// <param name="districtID">Unique identifier of district</param>
        /// <returns>String containing name of the district</returns>
        public static string GetDistrictName(int districtID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_DistrictNames.ContainsKey(districtID))
                    return cache_DistrictNames[districtID];
            }

            string name = String.Empty;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = "SELECT District AS DistrictName FROM District WHERE DistrictNo = @DistrictID";
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    name = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = "SELECT District AS DistrictName FROM District WHERE DistrictNo = @DistrictID";
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    name = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictName(districtID);
                    name = DataTransformation.Decrypt(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_DistrictNames[districtID] = name;
            return name;
        }

        /// <summary>
        /// Gets name of the region identified by region ID regionID
        /// </summary>
        /// <param name="regionID">Unique identifier of region</param>
        /// <returns>String containing name of the region</returns>
        public static string GetRegionName(int regionID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_RegionNames.ContainsKey(regionID))
                    return cache_RegionNames[regionID];
            }

            string name = String.Empty;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = "SELECT RegionName FROM Region WHERE RegionNo = @RegionNo";
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionNo";
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    name = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = "SELECT RegionName FROM Region WHERE RegionNo = @RegionNo";

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionNo";
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    name = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegionName(regionID);
                    name = DataTransformation.Decrypt(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_RegionNames[regionID] = name;
            return name;
        }

        /// <summary>
        /// Gets the name of the region where the district identified by district ID districtID is located.
        /// </summary>
        /// <param name="districtID">Unique identifier of district</param>
        /// <returns>String containing the name of the string</returns>
        public static string GetRegionNameFromDistrict(int districtID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_RegionNamesFromDistrictID.ContainsKey(districtID))
                    return cache_RegionNamesFromDistrictID[districtID];
            }
            string name = string.Empty;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = @"SELECT DISTINCT Region.RegionName FROM Facilities INNER JOIN District ON 
                        Facilities.District = District.DistrictNo INNER JOIN Region ON Facilities.Region = Region.RegionNo 
                        WHERE (District.DistrictNo = @DistrictID)";
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    name = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = @"SELECT DISTINCT Region.RegionName FROM (Facilities INNER JOIN District ON 
                        Facilities.District = District.DistrictNo) INNER JOIN Region ON Facilities.Region = Region.RegionNo 
                        WHERE (District.DistrictNo = @DistrictID)";
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = System.Data.DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    name = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegionNameFromDistrict(districtID);
                    name = DataTransformation.Decrypt(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_RegionNamesFromDistrictID[districtID] = name;
            return name;            
        }

        /// <summary>
        /// Gets details of Facility identified by facilityCode
        /// </summary>
        /// <param name="facilityCode">Unique identifier of Facility</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetFacilityDetails(string facilityCode)
        {
            //if (AppConfiguration.DataCached)
            //{
            //    if (cache_FacilityDetails.ContainsKey(facilityCode))
            //        return cache_FacilityDetails[facilityCode];
            //}

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter parameter = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT FacCode, FacName, FacShortName, Facilities.Region, Facilities.District,
                        LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, 
                        LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, FacilityType,
                        ProphylaxisStartDate, ActiveDate, Trained, ProvideDBS, InternalName, Activated,
                        SupportingPartnerId, Status, District.District AS DistrictName, Region.RegionName
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON Facilities.Region = Region.RegionNo
                        WHERE FacCode = @FacCode";
            
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = facilityCode;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    if (dataTable.Rows.Count > 0) cache_FacilityDetails[facilityCode] = dataTable;
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT FacCode, FacName, FacShortName, Facilities.Region, Facilities.District, PMTCT AS [PMTCTStatus],
                        LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                        LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, PMTCTStartDate, Prophylaxis, 
                        ProphylaxisStartDate, ActiveDate, InactiveDate, Trained, ProvideDBS, FacilityType,
                        SupportingPartnerId, Status, District.District AS DistrictName, Region.RegionName
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON Facilities.Region = Region.RegionNo
                        WHERE FacCode = @FacCode";
            
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = facilityCode;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    if (dataTable.Rows.Count > 0) cache_FacilityDetails[facilityCode] = dataTable;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityDetails(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            //if (AppConfiguration.DataCached) cache_FacilityDetails[facilityCode] = dataTable;
            return dataTable;            
        }

        /// <summary>
        /// Gets district where facility identified by facilityCode is located
        /// </summary>
        /// <param name="facilityCode">Unique identifier of Facility</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetFacilityDistrict(string facilityCode)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilityDistrict.ContainsKey(facilityCode))
                    return cache_FacilityDistrict[facilityCode];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT District.DistrictNo, District.District, District.RegionNo AS RegionID 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo
                        WHERE (Facilities.FacCode = @FacilityCode) ORDER BY District.District ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT District.DistrictNo, District.District, District.RegionNo AS RegionID 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo
                        WHERE (Facilities.FacCode = @FacilityCode) ORDER BY District.District ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityDistrict(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_FacilityDistrict[facilityCode] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Gets region where facility identified by facilityCode is located
        /// </summary>
        /// <param name="facilityCode">Unique identifier of facility</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetFacilityRegion(string facilityCode)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilityRegion.ContainsKey(facilityCode))
                    return cache_FacilityRegion[facilityCode];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            string query = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Region.RegionNo AS RegionID, Region.RegionName FROM Facilities INNER JOIN
                        Region ON Facilities.Region = Region.RegionNo WHERE (Facilities.FacCode = @FacilityCode)
                        ORDER BY RegionName ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Region.RegionNo AS RegionID, Region.RegionName FROM Facilities INNER JOIN
                        Region ON Facilities.Region = Region.RegionNo WHERE (Facilities.FacCode = @FacilityCode)
                        ORDER BY RegionName ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityRegion(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilityRegion[facilityCode] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Returns all facilities
        /// </summary>
        /// <returns>DataTable object</returns>
        [Obsolete("For simple list of facilities use GetAllFacilitiesStatus instead")]
        public static DataTable GetAllFacilities()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllFacilities != null) return cache_AllFacilities;
            }

            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
//                    string query = @"SELECT Facilities.FacCode, Facilities.FacName, 
//                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
//                        District.District AS [District Name], Region.RegionName AS [Region Name] 
//                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
//                        INNER JOIN Region ON District.RegionNo = Region.RegionNo";

                    string query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                        LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                        LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, PMTCTStartDate, Prophylaxis, 
                        ProphylaxisStartDate, ActiveDate, InactiveDate FROM Facilities ORDER BY FacName ASC";

                    //string query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT, LD, 
                    //  PMTCTYear, PMTCTPeriod, LDYear, LDPeriod FROM Facilities ORDER BY FacName ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilities();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_AllFacilities = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Returns all districts
        /// </summary>
        /// <returns>DataTable object</returns>
        public static DataTable GetAllDistricts()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllDistricts != null) return cache_AllDistricts;
            }
            
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DistrictNo, District, DistrictCode FROM District ORDER BY District ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT DistrictNo, District, DistrictCode FROM District ORDER BY District ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllDistricts();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            

            if (AppConfiguration.DataCached) cache_AllDistricts = dataTable;
            return dataTable;
        }

        public static DataTable GetAllDistricts(int supportingPartnerId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllDistricts != null) return cache_AllDistricts;
            }

            DataTable dataTable = null;
            string query = null;
            DbParameter param = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DISTINCT District.DistrictNo, District.District, District.DistrictCode
                            FROM District INNER JOIN Facilities ON District.DistrictNo = Facilities.District
                            WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                            ORDER BY District.District";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT DISTINCT District.DistrictNo, District.District, District.DistrictCode
                            FROM District INNER JOIN Facilities ON District.DistrictNo = Facilities.District
                            WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                            ORDER BY District.District";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllDistrictsBySupportingPartner(supportingPartnerId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_AllDistricts = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Get all districts in region identified by regionID
        /// </summary>
        /// <param name="regionID">Unique identifier of region</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetDistrictsByRegion(int regionID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_DistrictByRegionID.ContainsKey(regionID))
                    return cache_DistrictByRegionID[regionID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DistrictNo, District FROM District 
                        WHERE RegionNo = @RegionID ORDER BY District ASC";
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);            
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DistrictNo, District FROM District 
                        WHERE RegionNo = @RegionID ORDER BY District ASC";
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);            
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictsByRegion(regionID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached)
            {
                cache_DistrictByRegionID[regionID] = dataTable;
            }
            return dataTable;
        }

        public static DataTable GetDistrictsByRegion(int regionID, int supportingPartnerId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_DistrictByRegionID.ContainsKey(regionID))
                    return cache_DistrictByRegionID[regionID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DISTINCT DistrictNo, District.District 
                        FROM  District INNER JOIN Facilities ON District.DistrictNo = Facilities.District 
                        WHERE (RegionNo = @RegionID) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)
                        ORDER BY District ASC";

                    param = command.CreateParameter();
                    param.ParameterName = "@RegionID";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DISTINCT DistrictNo, District.District 
                        FROM  District INNER JOIN Facilities ON District.DistrictNo = Facilities.District 
                        WHERE (RegionNo = @RegionID) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)
                        ORDER BY District ASC";

                    param = command.CreateParameter();
                    param.ParameterName = "@RegionID";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictsByRegionBySupportingPartner(regionID, supportingPartnerId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached)
            {
                cache_DistrictByRegionID[regionID] = dataTable;
            }
            return dataTable;
        }

        public static DataTable GetDistrict(int districtID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_DistrictDetails.ContainsKey(districtID))
                    return cache_DistrictDetails[districtID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DistrictNo, District FROM District WHERE DistrictNo = @DistrictID 
                        ORDER BY District";
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);            
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DistrictNo, District FROM District WHERE DistrictNo = @DistrictID 
                        ORDER BY District";
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);            
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrict(districtID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_DistrictDetails[districtID] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Gets region where district identified by districtID is located
        /// </summary>
        /// <param name="districtID">Unique identifier of district</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetDistrictRegion(int districtID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_DistrictRegion.ContainsKey(districtID))
                    return cache_DistrictRegion[districtID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Region.RegionNo AS RegionID, Region.RegionName FROM District INNER JOIN
                        Region ON District.RegionNo = Region.RegionNo WHERE (District.DistrictNo = @DistrictID)
                        ORDER BY RegionName ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Region.RegionNo AS RegionID, Region.RegionName FROM District INNER JOIN
                        Region ON District.RegionNo = Region.RegionNo WHERE (District.DistrictNo = @DistrictID)
                        ORDER BY RegionName ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictRegion(districtID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_DistrictRegion[districtID] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Returns all regions
        /// </summary>
        /// <returns>DataTable object</returns>
        public static DataTable GetAllRegions()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllRegions != null)
                    return cache_AllRegions;
            }

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT RegionNo AS RegionID, RegionName, RegionCode FROM Region ORDER BY RegionName ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT RegionNo AS RegionID, RegionName, RegionCode FROM Region ORDER BY RegionName ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllRegions();
                    dataTable = GenericTools.DataTransformation.Deserialize(output);
                    break;
            }
                        
            if (AppConfiguration.DataCached) cache_AllRegions = dataTable;
            return dataTable;
        }

        public static DataTable GetAllRegions(int supportingPartnerId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllRegions != null)
                    return cache_AllRegions;
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DISTINCT Region.RegionNo AS RegionID, Region.RegionName, Region.RegionCode
                        FROM Region INNER JOIN Facilities ON Region.RegionNo = Facilities.Region
                        WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                        ORDER BY Region.RegionName";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT DISTINCT Region.RegionNo AS RegionID, Region.RegionName, Region.RegionCode
                        FROM Region INNER JOIN Facilities ON Region.RegionNo = Facilities.Region
                        WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                        ORDER BY Region.RegionName";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllRegionsBySupportingPartner(supportingPartnerId);
                    dataTable = GenericTools.DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_AllRegions = dataTable;
            return dataTable;
        }

        public static DataTable GetRegion(int regionID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_RegionDetails.ContainsKey(regionID))
                    return cache_RegionDetails[regionID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT RegionNo AS RegionID, RegionName FROM Region 
                        WHERE RegionNo=@RegionNo ORDER BY RegionName ASC";

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionNo";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT RegionNo AS RegionID, RegionName FROM Region 
                        WHERE RegionNo=@RegionNo ORDER BY RegionName ASC";

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionNo";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegion(regionID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_RegionDetails[regionID] = dataTable;
            return dataTable;
        }

        #region Submitted Reports
        public static DataTable GetSumittedFacilityReport(string facilityCode, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }

                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetSubmittedFacilityReport(facilityCode,
                                    report, currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetSubmittedFacilityReport(facilityCode, report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSubmittedFacilityReport(facilityCode, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }        

        private static DataTable GetSubmittedFacilityReport(string facilityCode, int report,
            int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
//            command.CommandText = @"SELECT FacCode AS [Facility Code], FacName AS [Facility Name], 
//                @Year AS [Year], @Period AS Period 
//                FROM Facilities WHERE (FacCode IN (SELECT FacCode FROM ReceivedSMS 
//                WHERE (RepID = @RepID) AND (Period = @Period) AND ([Year] = @Year))) 
//                AND (FacCode = @FacCode) AND (Facilities.Activated = 1)";

            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                ReceivedSMS.Year, ReceivedSMS.Period, ReceivedSMS.Comments FROM Facilities INNER JOIN
                ReceivedSMS ON Facilities.FacCode = ReceivedSMS.FacCode
                WHERE (Facilities.Activated = 1) AND (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period = @Period) 
                AND (ReceivedSMS.FacCode = @FacCode) AND (ReceivedSMS.RepID = @RepID)";

            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);                   

            param = command.CreateParameter();
            param.ParameterName = "@FacCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);

            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }       

        private static DataTable GetSubmittedDistrictReport(int districtID, int report,
            int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
//            command.CommandText = @"SELECT FacCode, FacName, @Year AS [Year], @Period AS Period 
//                FROM Facilities WHERE (FacCode IN (SELECT FacCode FROM ReceivedSMS 
//                WHERE (RepID = @RepID) AND (Period = @Period) AND ([Year] = @Year))) 
//                AND (District = @DistrictID) AND (Facilities.Activated = 1)";

            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                ReceivedSMS.Year, ReceivedSMS.Period, ReceivedSMS.Comments FROM Facilities INNER JOIN
                ReceivedSMS ON Facilities.FacCode = ReceivedSMS.FacCode
                WHERE (Facilities.Activated = 1) AND (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period = @Period) 
                AND (ReceivedSMS.RepID = @RepID) AND (Facilities.District = @DistrictId)";

            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@DistrictID";
            param.DbType = DbType.Int32;
            param.Value = districtID;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);

            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }       

        private static DataTable GetSubmittedRegionReport(int regionID, int report,
            int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
//            command.CommandText = @"SELECT FacCode, FacName, @Year AS [Year], @Period AS Period 
//                FROM Facilities WHERE (FacCode IN (SELECT FacCode FROM ReceivedSMS 
//                WHERE (RepID = @RepID) AND (Period = @Period) AND ([Year] = @Year))) 
//                AND (Region = @RegionID) AND (Facilities.Activated = 1)";

            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                ReceivedSMS.Year, ReceivedSMS.Period, ReceivedSMS.Comments FROM Facilities INNER JOIN
                ReceivedSMS ON Facilities.FacCode = ReceivedSMS.FacCode
                WHERE (Facilities.Activated = 1) AND (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period = @Period) 
                AND (ReceivedSMS.RepID = @RepID) AND (Facilities.Region = @RegionID)";

            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@RegionID";
            param.DbType = DbType.Int32;
            param.Value = regionID;
            command.Parameters.Add(param);  

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);

            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }       

        private static DataTable GetSubmittedNationReport(int report, int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
//            command.CommandText = @"SELECT FacCode, FacName, @Year AS [Year], @Period AS Period 
//                FROM Facilities WHERE (FacCode IN (SELECT FacCode FROM ReceivedSMS 
//                WHERE (RepID = @RepID) AND (Period = @Period) AND ([Year] = @Year))) AND (Facilities.Activated = 1)";

            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                ReceivedSMS.Year, ReceivedSMS.Period, ReceivedSMS.Comments FROM Facilities INNER JOIN
                ReceivedSMS ON Facilities.FacCode = ReceivedSMS.FacCode
                WHERE (Facilities.Activated = 1) AND (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period = @Period) 
                AND (ReceivedSMS.RepID = @RepID)";

            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);


            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }

        public static DataTable GetSubmittedDistrictReport(int districtID, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetSubmittedDistrictReport(districtID,
                                    report, currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetSubmittedDistrictReport(districtID, report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSubmittedDistrictReport(districtID, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        public static DataTable GetSubmittedRegionReport(int regionID, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }

                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetSubmittedRegionReport(regionID,
                                    report, currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetSubmittedRegionReport(regionID, report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSubmittedRegionReport(regionID, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        public static DataTable GetSubmittedNationReport(int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetSubmittedNationReport(report,
                                    currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetSubmittedNationReport(report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSubmittedNationReport(report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }        
        #endregion        

        #region Missing Reports
        public static DataTable GetMissingDistrictReport(int districtID, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetMissingDistrictReport(districtID,
                                    report, currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetMissingDistrictReport(districtID, report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetMissingDistrictReport(districtID, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        public static DataTable GetMissingRegionReport(int regionID, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetMissingRegionReport(regionID,
                                    report, currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetMissingRegionReport(regionID, report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetMissingRegionReport(regionID, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        public static DataTable GetMissingNationReport(int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetMissingNationReport(report,
                                    currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetMissingNationReport(report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetMissingNationReport(report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        private static DataTable GetMissingNationReport(int report, int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                @Year AS Year, @Period AS Period FROM Facilities INNER JOIN ExpectedReports ON 
                Facilities.FacCode = ExpectedReports.FacCode WHERE (Facilities.FacCode NOT IN
                (SELECT FacCode FROM ReceivedSMS WHERE (RepID = @RepID) AND (Period = @Period) AND (Year = @Year))) 
                AND (ExpectedReports.ReportID = @RepID) 
                AND (CAST(CAST(@Year AS varchar(4)) + '-' + CAST(@Period AS varchar(2)) + '-01' AS datetime) 
                >= ExpectedReports.ReportingStartDate) AND (Facilities.Activated = 1)";
            //            command.CommandText = @"SELECT Facilities.FacCode, FacName, @Year AS [Year], @Period AS Period 
            //                FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode
            //                WHERE (Facilities.FacCode NOT IN (SELECT FacCode FROM ReceivedSMS 
            //                WHERE (RepID = @RepID) AND (Period = @Period) AND ([Year] = @Year))) AND (ExpectedReports.ReportID = @RepID)";
            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);

            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }

        private static DataTable GetMissingRegionReport(int regionID, int report,
            int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                @Year AS Year, @Period AS Period FROM Facilities INNER JOIN ExpectedReports ON 
                Facilities.FacCode = ExpectedReports.FacCode WHERE (Facilities.FacCode NOT IN
                (SELECT FacCode FROM ReceivedSMS WHERE (RepID = @RepID) AND (Period = @Period) AND (Year = @Year))) 
                AND (Region = @RegionID) AND (ExpectedReports.ReportID = @RepID) 
                AND (CAST(CAST(@Year AS varchar(4)) + '-' + CAST(@Period AS varchar(2)) + '-01' AS datetime) 
                >= ExpectedReports.ReportingStartDate) AND (Facilities.Activated = 1)";
            //            command.CommandText = @"SELECT Facilities.FacCode, FacName, @Year AS [Year], @Period AS Period 
            //                FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode
            //                WHERE (Facilities.FacCode NOT IN (SELECT FacCode FROM ReceivedSMS 
            //                WHERE (RepID = @RepID) AND (Period = @Period) AND ([Year] = @Year))) 
            //                AND (Region = @RegionID) AND (ExpectedReports.ReportID = @RepID)";
            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@RegionID";
            param.DbType = DbType.Int32;
            param.Value = regionID;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);

            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }

        public static DataTable GetMissingFacilityReport(string facilityCode, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    do
                    {
                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                if (reportCount == null) reportCount = GetMissingFacilityReport(facilityCode,
                                    report, currentYear, currentPeriod, command);
                                else
                                {
                                    DataTable temp = GetMissingFacilityReport(facilityCode, report,
                                        currentYear, currentPeriod, command);
                                    reportCount.Merge(temp);
                                }
                            }
                        }

                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetMissingFacilityReport(facilityCode, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        private static DataTable GetMissingDistrictReport(int districtID, int report,
            int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                @Year AS Year, @Period AS Period FROM Facilities INNER JOIN ExpectedReports ON 
                Facilities.FacCode = ExpectedReports.FacCode WHERE (Facilities.FacCode NOT IN
                (SELECT FacCode FROM ReceivedSMS WHERE (RepID = @RepID) AND (Period = @Period) AND (Year = @Year))) 
                AND (District = @DistrictID) AND (ExpectedReports.ReportID = @RepID) 
                AND (CAST(CAST(@Year AS varchar(4)) + '-' + CAST(@Period AS varchar(2)) + '-01' AS datetime) 
                >= ExpectedReports.ReportingStartDate) AND (Facilities.Activated = 1)";
            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@DistrictID";
            param.DbType = DbType.Int32;
            param.Value = districtID;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);
            
            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }

            return dataTable;
        }

        private static DataTable GetMissingFacilityReport(string facilityCode, int report,
            int year, int period, DbCommand command)
        {
            command.CommandType = CommandType.Text;
            command.CommandText = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                @Year AS Year, @Period AS Period FROM Facilities INNER JOIN ExpectedReports ON 
                Facilities.FacCode = ExpectedReports.FacCode WHERE (Facilities.FacCode NOT IN
                (SELECT FacCode FROM ReceivedSMS WHERE (RepID = @RepID) AND (Period = @Period) AND (Year = @Year))) 
                AND (Facilities.FacCode = @FacCode) AND (ExpectedReports.ReportID = @RepID) 
                AND (CAST(CAST(@Year AS varchar(4)) + '-' + CAST(@Period AS varchar(2)) + '-01' AS datetime) 
                >= ExpectedReports.ReportingStartDate) AND (Facilities.Activated = 1)";
            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = report;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@FacCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);
            
            // This is a special requirement for quarterly MTUHA MC if applicable.
            if (((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0) && dataTable.Rows.Count > 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int reportId;
                    bool converted = int.TryParse(s, out reportId);
                    if (converted && report == reportId) dataTable.Rows.Clear();
                }
            }
            return dataTable;
        }        
        #endregion        

        #region Report Counting
        public static DataTable GetDistrictReportCount(int districtID, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    command.CommandType = CommandType.Text;

                    reportCount = new DataTable();
                    DataColumn column = new DataColumn("Year", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Period", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Report Count", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);

                    command.CommandText = @"SELECT FacCode FROM Facilities WHERE District=@DistrictID AND (Facilities.Activated = 1)";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    DataTable facilities = GenericDataAccess.ExecuteSelectCommand(command, false);

                    if (facilities.Rows.Count > 0)
                    {
                        // This is a special requirement for quarterly MTUHA MC if applicable
                        int mtuhaQuarterReportId = -1;
                        int quarterInterval = Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS;
                        var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                        if (!string.IsNullOrWhiteSpace(s))
                        {
                            bool converted = int.TryParse(s, out mtuhaQuarterReportId);
                            if (!converted) mtuhaQuarterReportId = -1;
                        }

                        int currentPeriod = startPeriod;
                        int currentYear = startYear;
                        DataRow row = null;

                        if (report == mtuhaQuarterReportId && ((currentPeriod % quarterInterval) != 0)) { }
                        else
                        {
                            row = reportCount.NewRow();
                            row["Year"] = startYear;
                            row["Period"] = startPeriod;
                            int count = 0;
                            for (int i = 0; i < facilities.Rows.Count; i++)
                            {
                                string code = facilities.Rows[i][0].ToString();
                                count += GetFacilityReportCount(code, report,
                                    startYear, startPeriod, command);
                            }
                            row["Report Count"] = count;
                            reportCount.Rows.Add(row);
                        }
                        
                        do
                        {
                            currentPeriod++;
                            if (currentPeriod > 12)
                            {
                                currentPeriod = 1;
                                currentYear++;
                            }

                            if (currentYear > endYear) break;
                            else
                            {
                                if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                                else
                                {
                                    if (report == mtuhaQuarterReportId && ((currentPeriod % quarterInterval) != 0)) continue;
                                    else
                                    {
                                        row = reportCount.NewRow();
                                        row["Year"] = currentYear;
                                        row["Period"] = currentPeriod;

                                        int count = 0;
                                        for (int i = 0; i < facilities.Rows.Count; i++)
                                        {
                                            string code = facilities.Rows[i][0].ToString();
                                            count += GetFacilityReportCount(code, report,
                                                currentYear, currentPeriod, command);
                                        }
                                        row["Report Count"] = count;
                                        reportCount.Rows.Add(row);
                                    }
                                }
                            }
                        } while (true);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictReportCount(districtID, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }

        public static DataTable GetRegionReportCount(int regionID, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    command.CommandType = CommandType.Text;

                    reportCount = new DataTable();
                    DataColumn column = new DataColumn("Year", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Period", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Report Count", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);

                    command.CommandText = @"SELECT FacCode FROM Facilities WHERE Region=@RegionID AND (Facilities.Activated = 1)";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RegionID";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);
                    DataTable facilities = GenericDataAccess.ExecuteSelectCommand(command, false);

                    if (facilities.Rows.Count > 0)
                    {
                        // This is a special requirement for quarterly MTUHA MC if applicable
                        int mtuhaQuarterReportId = -1;
                        int quarterInterval = Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS;
                        var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                        if (!string.IsNullOrWhiteSpace(s))
                        {
                            bool converted = int.TryParse(s, out mtuhaQuarterReportId);
                            if (!converted) mtuhaQuarterReportId = -1;
                        }

                        int currentPeriod = startPeriod;
                        int currentYear = startYear;
                        DataRow row = null;

                        if (report == mtuhaQuarterReportId && ((currentPeriod % quarterInterval) != 0)) { }
                        else
                        {
                            row = reportCount.NewRow();
                            row["Year"] = startYear;
                            row["Period"] = startPeriod;
                            int count = 0;
                            for (int i = 0; i < facilities.Rows.Count; i++)
                            {
                                string code = facilities.Rows[i][0].ToString();
                                count += GetFacilityReportCount(code, report,
                                    startYear, startPeriod, command);
                            }
                            row["Report Count"] = count;
                            reportCount.Rows.Add(row);
                        }

                        do
                        {
                            currentPeriod++;
                            if (currentPeriod > 12)
                            {
                                currentPeriod = 1;
                                currentYear++;
                            }

                            if (currentYear > endYear) break;
                            else
                            {
                                if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                                else
                                {
                                    if (report == mtuhaQuarterReportId && ((currentPeriod % quarterInterval) != 0)) continue;
                                    else
                                    {
                                        row = reportCount.NewRow();
                                        row["Year"] = currentYear;
                                        row["Period"] = currentPeriod;

                                        int count = 0;
                                        for (int i = 0; i < facilities.Rows.Count; i++)
                                        {
                                            string code = facilities.Rows[i][0].ToString();
                                            count += GetFacilityReportCount(code, report,
                                                currentYear, currentPeriod, command);
                                        }
                                        row["Report Count"] = count;
                                        reportCount.Rows.Add(row);
                                    }
                                }
                            }
                        } while (true);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegionReportCount(regionID, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }                

        public static DataTable GetNationReportCount(int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                        command.CommandType = CommandType.Text;
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                        command.CommandType = CommandType.Text;
                    }

                    reportCount = new DataTable();
                    DataColumn column = new DataColumn("Year", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Period", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Report Count", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);

                    command.CommandText = @"SELECT FacCode FROM Facilities WHERE (Facilities.Activated = 1)";
                    DataTable facilities = GenericDataAccess.ExecuteSelectCommand(command, false);

                    if (facilities.Rows.Count > 0)
                    {
                        // This is a special requirement for quarterly MTUHA MC if applicable
                        int mtuhaQuarterReportId = -1;
                        int quarterInterval = Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS;
                        var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                        if (!string.IsNullOrWhiteSpace(s))
                        {
                            bool converted = int.TryParse(s, out mtuhaQuarterReportId);
                            if (!converted) mtuhaQuarterReportId = -1;
                        }

                        int currentPeriod = startPeriod;
                        int currentYear = startYear;
                        DataRow row = null;

                        if (report == mtuhaQuarterReportId && ((currentPeriod % quarterInterval) != 0)) { }
                        else
                        {
                            row = reportCount.NewRow();
                            row["Year"] = startYear;
                            row["Period"] = startPeriod;
                            int count = 0;
                            for (int i = 0; i < facilities.Rows.Count; i++)
                            {
                                string code = facilities.Rows[i][0].ToString();
                                count += GetFacilityReportCount(code, report,
                                    startYear, startPeriod, command);
                            }
                            row["Report Count"] = count;
                            reportCount.Rows.Add(row);
                        }

                        do
                        {
                            currentPeriod++;
                            if (currentPeriod > 12)
                            {
                                currentPeriod = 1;
                                currentYear++;
                            }

                            if (currentYear > endYear) break;
                            else
                            {
                                if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                                else
                                {
                                    if (report == mtuhaQuarterReportId && ((currentPeriod % quarterInterval) != 0)) continue;
                                    else
                                    {
                                        row = reportCount.NewRow();
                                        row["Year"] = currentYear;
                                        row["Period"] = currentPeriod;

                                        int count = 0;
                                        for (int i = 0; i < facilities.Rows.Count; i++)
                                        {
                                            string code = facilities.Rows[i][0].ToString();
                                            count += GetFacilityReportCount(code, report,
                                                currentYear, currentPeriod, command);
                                        }
                                        row["Report Count"] = count;
                                        reportCount.Rows.Add(row);
                                    }
                                }
                            }
                        } while (true);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetNationReportCount(report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }
        private static int GetFacilityReportCount(string facilityCode, int reportID,
            int year, int period, DbCommand command)
        {
            int count = 0;
            // This is a special requirement for quarterly MTUHA MC if applicable.
            if ((period % Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS) != 0)
            {
                var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                if (!string.IsNullOrWhiteSpace(s))
                {
                    int mtuhaMCReportId;
                    bool converted = int.TryParse(s, out mtuhaMCReportId);
                    if (converted && (reportID == mtuhaMCReportId)) return 0;
                }
            }

            command.CommandType = CommandType.Text;
            command.CommandText = @"SELECT COUNT(RepID) AS [count] FROM ReceivedSMS 
                WHERE (RepID = @RepID) AND (Period = @Period) AND (FacCode = @FacCode) AND ([Year] = @Year)";

            command.Parameters.Clear();
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RepID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@FacCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            string output = GenericDataAccess.ExecuteScalar(command, false);
            count = Int32.Parse(output);
            return count;
        }

        public static DataTable GetFacilityReportCount(string facilityCode, int report, int startYear,
            int startPeriod, int endYear, int endPeriod)
        {
            DataTable reportCount = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if ((AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS) ||
                        (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DIRECT_ACCESS))
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }

                    reportCount = new DataTable();
                    DataColumn column = new DataColumn("Year", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Period", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);
                    column = new DataColumn("Report Count", Type.GetType("System.Int32"));
                    reportCount.Columns.Add(column);

                    int currentPeriod = startPeriod;
                    int currentYear = startYear;
                    DataRow row = null;

                    // This is a special requirement for quarterly MTUHA MC if applicable.
                    int mtuhaQuarterReportId = -1;
                    int quarterInterval = Configurations.SystemSetting.MTUHA_MC_REPORT_INTERVAL_MONTHS;
                    if ((currentPeriod % quarterInterval) != 0)
                    {
                        var s = Configurations.SystemSetting.GetSetting(Configurations.SystemConfig.MTUHA_MC_REPORT_ID);
                        if (!string.IsNullOrWhiteSpace(s))
                        {
                            bool converted = int.TryParse(s, out mtuhaQuarterReportId);
                            if (converted)
                            {
                                if (mtuhaQuarterReportId != report)
                                {
                                    row = reportCount.NewRow();
                                    row["Year"] = startYear;
                                    row["Period"] = startPeriod;
                                    row["Report Count"] = GetFacilityReportCount(facilityCode, report,
                                        startYear, startPeriod, command);
                                    reportCount.Rows.Add(row);
                                }
                            }
                            else
                            {
                                mtuhaQuarterReportId = -1;
                                row = reportCount.NewRow();
                                row["Year"] = startYear;
                                row["Period"] = startPeriod;
                                row["Report Count"] = GetFacilityReportCount(facilityCode, report,
                                    startYear, startPeriod, command);
                                reportCount.Rows.Add(row);
                            }
                        }
                    }
                    else
                    {
                        row = reportCount.NewRow();
                        row["Year"] = startYear;
                        row["Period"] = startPeriod;
                        row["Report Count"] = GetFacilityReportCount(facilityCode, report,
                            startYear, startPeriod, command);
                        reportCount.Rows.Add(row);
                    }
                    
                    do
                    {
                        currentPeriod++;
                        if (currentPeriod > 12)
                        {
                            currentPeriod = 1;
                            currentYear++;
                        }

                        if (currentYear > endYear) break;
                        else
                        {
                            if ((currentYear == endYear) && (currentPeriod > endPeriod)) break;
                            else
                            {
                                // This is a special requirement for quarterly MTUHA MC if applicable.
                                // We skip months which are not last months of the quarter
                                if (((currentPeriod % quarterInterval) != 0) && (report == mtuhaQuarterReportId)) continue;

                                row = reportCount.NewRow();
                                row["Year"] = currentYear;
                                row["Period"] = currentPeriod;
                                row["Report Count"] = GetFacilityReportCount(facilityCode, report,
                                    currentYear, currentPeriod, command);
                                reportCount.Rows.Add(row);
                            }
                        }
                    } while (true);
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityReportCount(facilityCode, report, startYear,
                        startPeriod, endYear, endPeriod);
                    reportCount = DataTransformation.Deserialize(output);
                    break;
            }
            return reportCount;
        }
        #endregion        

        #region Private GetReport Methods
        private static DataTable GetFacilityReport(string facilityCode, int reportID, int year,
            int startPeriod, int endPeriod, bool basicInfo)
        {
            DataTable dataTable = null;
            DbCommand command = null;

            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData
                    FROM ReportData INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo
                    WHERE (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND 
                    (ReportData.RepID = rdl.RepID) AND (ReportData.DataPosition = rdl.DataPosition) AND (ReceivedSMS.FacCode = @FacilityCode)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData
                    FROM ReportData INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo
                    WHERE (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND 
                    (ReportData.RepID = rdl.RepID) AND (ReportData.DataPosition = rdl.DataPosition) AND (ReceivedSMS.FacCode = @FacilityCode)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], (SELECT SUM(ReportData.Data) AS ReportData
                    FROM ReportData INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo
                    WHERE (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND 
                    (ReportData.RepID = rdl.RepID) AND (ReportData.DataPosition = rdl.DataPosition) AND (ReceivedSMS.FacCode = @FacilityCode)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], (SELECT SUM(ReportData.Data) AS ReportData
                    FROM ReportData INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo
                    WHERE (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND 
                    (ReportData.RepID = rdl.RepID) AND (ReportData.DataPosition = rdl.DataPosition) AND (ReceivedSMS.FacCode = @FacilityCode)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;
            }                       
            
            #region Setting Parameters
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@StartPeriod";
            param.DbType = DbType.Int32;
            param.Value = startPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@EndPeriod";
            param.DbType = DbType.Int32;
            param.Value = endPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@FacilityCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);
            #endregion
            dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        private static DataTable GetDistrictReport(int districtID, int reportID,  int year, 
            int startPeriod, int endPeriod, bool basicInfo)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], 
                    (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE (ReceivedSMS.Year = @Year) AND 
                    (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition)
                    AND (Facilities.District = @DistrictID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], 
                    (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE (ReceivedSMS.Year = @Year) AND 
                    (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition)
                    AND (Facilities.District = @DistrictID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], 
                    (SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE (ReceivedSMS.Year = @Year) AND 
                    (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition)
                    AND (Facilities.District = @DistrictID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], 
                    (SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE (ReceivedSMS.Year = @Year) AND 
                    (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition)
                    AND (Facilities.District = @DistrictID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;
            }
            
            
            #region Setting Parameters
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@StartPeriod";
            param.DbType = DbType.Int32;
            param.Value = startPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@EndPeriod";
            param.DbType = DbType.Int32;
            param.Value = endPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@DistrictID";
            param.DbType = DbType.Int32;
            param.Value = districtID;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);
            #endregion
            dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        private static DataTable GetRegionReport(int regionID, int reportID, int year, 
            int startPeriod, int endPeriod, bool basicInfo)
        {
            DataTable dataTable = null;
            DbCommand command = null; 
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], 
                    (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition) 
                    AND (Facilities.Region = @RegionID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], 
                    (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition) 
                    AND (Facilities.Region = @RegionID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], 
                    (SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition) 
                    AND (Facilities.Region = @RegionID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], 
                    (SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.RepID = rdl.RepID)  AND (ReportData.DataPosition = rdl.DataPosition) 
                    AND (Facilities.Region = @RegionID) AND (Facilities.Activated = 1)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;
            }
            
            
            #region Setting Parameters
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@StartPeriod";
            param.DbType = DbType.Int32;
            param.Value = startPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@EndPeriod";
            param.DbType = DbType.Int32;
            param.Value = endPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@RegionID";
            param.DbType = DbType.Int32;
            param.Value = regionID;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);
            #endregion
            dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        private static DataTable GetNationReport(int reportID, int year, int startPeriod,
            int endPeriod, bool basicInfo)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], 
                    (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (Facilities.Activated = 1) AND  (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.DataPosition = rdl.DataPosition) AND (ReportData.RepID = rdl.RepID)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], 
                    (SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (Facilities.Activated = 1) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.DataPosition = rdl.DataPosition) AND (ReportData.RepID = rdl.RepID)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    if (basicInfo)
                    {
                        command.CommandText = @"SELECT ShortCode AS [Data Description], 
                    (SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (Facilities.Activated = 1) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.DataPosition = rdl.DataPosition) AND (ReportData.RepID = rdl.RepID)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    else
                    {
                        command.CommandText = @"SELECT DataDescription AS [Data Description], 
                    (SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                    INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                    Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                    (ReceivedSMS.Year = @Year) AND (Facilities.Activated = 1) AND (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) 
                    AND (ReportData.DataPosition = rdl.DataPosition) AND (ReportData.RepID = rdl.RepID)) AS Data
                    FROM ReportDataLocations AS rdl WHERE (RepID = @ReportID) AND (DataPosition > 3)";
                    }
                    break;
            }
            
            
            #region Setting Parameters
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@StartPeriod";
            param.DbType = DbType.Int32;
            param.Value = startPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@EndPeriod";
            param.DbType = DbType.Int32;
            param.Value = endPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);
            #endregion
            dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }
        #endregion

        #region Public GetReport Methods
        public static DataTable GetFacilityReport(string facilityCode, int reportID, int startYear,
            int startPeriod, int endYear, int endPeriod, bool basicInfo = false)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    if (startYear == endYear)
                    {
                        dataTable = GetFacilityReport(facilityCode, reportID, 
                            startYear, startPeriod, endPeriod, basicInfo);
                    }
                    else
                    {
                        int currentYear = startYear;
                        do
                        {
                            int startingPeriod = 1;
                            int endingPeriod = 12;
                            if (currentYear == startYear) startingPeriod = startPeriod;
                            if (currentYear == endYear) endingPeriod = endPeriod;

                            DataTable temp = GetFacilityReport(facilityCode, reportID, currentYear, 
                                startingPeriod, endingPeriod, basicInfo);
                            if (dataTable == null)
                            {
                                dataTable = temp;
                                dataTable.Columns[1].ReadOnly = false;
                            }
                            else
                            {
                                for (int i = 0; i < dataTable.Rows.Count; i++)
                                {
                                    DataRow row = dataTable.Rows[i];
                                    DataRow tempRow = temp.Rows[i];
                                    int value = Int32.Parse(row[1].ToString());
                                    int tempValue = Int32.Parse(tempRow[1].ToString());
                                    int newValue = value + tempValue;
                                    row[1] = newValue;
                                }
                            }
                            currentYear++;
                        } while (currentYear <= endYear);
                    }
                    dataTable.Columns[1].ReadOnly = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityReport2(facilityCode, reportID, 
                        startYear, startPeriod, endYear, endPeriod, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetDistrictReport(int districtID, int reportID, int startYear, int startPeriod,
            int endYear, int endPeriod, bool basicInfo = false)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    if (startYear == endYear)
                    {
                        dataTable = GetDistrictReport(districtID, reportID, startYear, startPeriod, endPeriod, basicInfo);
                    }
                    else
                    {
                        int currentYear = startYear;
                        do
                        {
                            int startingPeriod = 1;
                            int endingPeriod = 12;
                            if (currentYear == startYear) startingPeriod = startPeriod;
                            if (currentYear == endYear) endingPeriod = endPeriod;

                            DataTable temp = GetDistrictReport(districtID, reportID, currentYear,
                                startingPeriod, endingPeriod, basicInfo);
                            if (dataTable == null)
                            {
                                dataTable = temp;
                                dataTable.Columns[1].ReadOnly = false;
                            }
                            else
                            {
                                for (int i = 0; i < dataTable.Rows.Count; i++)
                                {
                                    DataRow row = dataTable.Rows[i];
                                    DataRow tempRow = temp.Rows[i];
                                    int value = Int32.Parse(row[1].ToString());
                                    int tempValue = Int32.Parse(tempRow[1].ToString());
                                    int newValue = value + tempValue;
                                    row[1] = newValue;
                                }
                            }
                            currentYear++;
                        } while (currentYear <= endYear);
                    }
                    dataTable.Columns[1].ReadOnly = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictReport2(districtID, reportID, startYear,
                        startPeriod, endYear, endPeriod, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            return dataTable;
        }

        public static DataTable GetRegionReport(int regionID, int reportID, int startYear, int startPeriod, 
            int endYear, int endPeriod, bool basicInfo = false)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    if (startYear == endYear)
                    {
                        dataTable = GetRegionReport(regionID, reportID, startYear, startPeriod, endPeriod, basicInfo);
                    }
                    else
                    {
                        int currentYear = startYear;
                        do
                        {
                            int startingPeriod = 1;
                            int endingPeriod = 12;
                            if (currentYear == startYear) startingPeriod = startPeriod;
                            if (currentYear == endYear) endingPeriod = endPeriod;

                            DataTable temp = GetRegionReport(regionID, reportID, currentYear,
                                startingPeriod, endingPeriod, basicInfo);
                            if (dataTable == null)
                            {
                                dataTable = temp;
                                dataTable.Columns[1].ReadOnly = false;
                            }
                            else
                            {
                                for (int i = 0; i < dataTable.Rows.Count; i++)
                                {
                                    DataRow row = dataTable.Rows[i];
                                    DataRow tempRow = temp.Rows[i];
                                    int value = Int32.Parse(row[1].ToString());
                                    int tempValue = Int32.Parse(tempRow[1].ToString());
                                    int newValue = value + tempValue;
                                    row[1] = newValue;
                                }
                            }
                            currentYear++;
                        } while (currentYear <= endYear);
                    }
                    dataTable.Columns[1].ReadOnly = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegionReport2(regionID, reportID, startYear, 
                        startPeriod, endYear, endPeriod, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            return dataTable;
        }

        public static DataTable GetNationReport(int reportID, int startYear, int startPeriod, int endYear, 
            int endPeriod, bool basicInfo = false)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    if (startYear == endYear)
                    {
                        dataTable = GetNationReport(reportID, startYear, startPeriod, endPeriod, basicInfo);
                    }
                    else
                    {
                        int currentYear = startYear;
                        do
                        {
                            int startingPeriod = 1;
                            int endingPeriod = 12;
                            if (currentYear == startYear) startingPeriod = startPeriod;
                            if (currentYear == endYear) endingPeriod = endPeriod;

                            DataTable temp = GetNationReport(reportID, currentYear,
                                startingPeriod, endingPeriod, basicInfo);
                            if (dataTable == null)
                            {
                                dataTable = temp;
                                dataTable.Columns[1].ReadOnly = false;
                            }
                            else
                            {
                                for (int i = 0; i < dataTable.Rows.Count; i++)
                                {
                                    DataRow row = dataTable.Rows[i];
                                    DataRow tempRow = temp.Rows[i];
                                    int value = Int32.Parse(row[1].ToString());
                                    int tempValue = Int32.Parse(tempRow[1].ToString());
                                    int newValue = value + tempValue;
                                    row[1] = newValue;
                                }
                            }
                            currentYear++;
                        } while (currentYear <= endYear);
                    }
                    dataTable.Columns[1].ReadOnly = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetNationReport2(reportID, startYear, 
                        startPeriod, endYear, endPeriod, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            
            return dataTable;
        }

        public const string DETAILS_TABLE_NAME = "DETAILS_TABLE_NAME";
        public const string SUBMITTED_TABLE_NAME = "SUBMITTED_TABLE_NAME";
        public const string MISSING_TABLE_NAME = "MISSING_TABLE_NAME";
        public const string DATA_COUNT_TABLE_NAME = "DATA_COUNT_TABLE_NAME";
        public const string SUBMISSION_INFO_TABLE_NAME = "SUBMISSION_INFO_TABLE_NAME";

        public static DataSet GetReportingInfo(AccessLevel requestLevel, string requestLevelValue, int reportId,
            int startYear, int startPeriod, int endYear, int endPeriod, AccessLevel userAccessLevel,
            int supportingPartnerId, bool basicInfo = false)
        {
            DataSet dataset = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    if (userAccessLevel == AccessLevel.ADMINISTRATOR) // This is system administrator making a request
                    {
                        dataset = GetReportingInfo(requestLevel, requestLevelValue, reportId,
                            startYear, startPeriod, endYear, endPeriod, basicInfo);
                    }
                    else
                    {
                        dataset = GetReportingInfo(requestLevel, requestLevelValue, reportId,
                            startYear, startPeriod, endYear, endPeriod, supportingPartnerId,
                            basicInfo);
                    }
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new NotImplementedException("This feature does not support MS Access back-end");

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportingInfo((IQServices.AccessLevel)requestLevel, 
                        requestLevelValue, reportId, startYear, startPeriod, endYear, endPeriod,
                        (IQServices.AccessLevel)userAccessLevel, supportingPartnerId, basicInfo);
                    dataset = DataTransformation.DeserializeDataSet(output, true);
                    break;
            }
            return dataset;
        }

        /// <summary>
        /// Getting reporting info - reserved for user with administrator priviledges
        /// </summary>
        /// <param name="accessLevel"></param>
        /// <param name="accessLevelValue"></param>
        /// <param name="reportId"></param>
        /// <param name="startYear"></param>
        /// <param name="startPeriod"></param>
        /// <param name="endYear"></param>
        /// <param name="endPeriod"></param>
        /// <param name="basicInfo"></param>
        /// <returns></returns>
        private static DataSet GetReportingInfo(AccessLevel accessLevel, string accessLevelValue, int reportId,
            int startYear, int startPeriod, int endYear, int endPeriod, bool basicInfo = false)
        {
            var dataset = new DataSet();
            DataTable detailsTable = null;
            DataTable dataCountTable = null;
            DataTable submissionTable = null;
            DataTable missingTable = null;
            DataTable submissionInfoTable = null;

            switch (accessLevel)
            {
                case AccessLevel.ADMINISTRATOR:
                case AccessLevel.NATION:
                    detailsTable = GetNationReport(reportId, startYear, startPeriod, endYear, endPeriod, basicInfo);
                    dataCountTable = GetNationReportCount(reportId, startYear, startPeriod, endYear, endPeriod);
                    submissionTable = GetSubmittedNationReport(reportId, startYear, startPeriod, endYear, endPeriod);
                    missingTable = GetMissingNationReport(reportId, startYear, startPeriod, endYear, endPeriod);
                    break;

                case AccessLevel.REGION:
                    int regionId = int.Parse(accessLevelValue);
                    detailsTable = GetRegionReport(regionId, reportId, startYear, startPeriod, endYear, endPeriod, basicInfo);
                    dataCountTable = GetRegionReportCount(regionId, reportId, startYear, startPeriod, endYear, endPeriod);
                    submissionTable = GetSubmittedRegionReport(regionId, reportId, startYear, startPeriod, endYear, endPeriod);
                    missingTable = GetMissingRegionReport(regionId, reportId, startYear, startPeriod, endYear, endPeriod);
                    break;

                case AccessLevel.DISTRICT:
                    int districtId = int.Parse(accessLevelValue);
                    detailsTable = GetDistrictReport(districtId, reportId, startYear, startPeriod, endYear, endPeriod, basicInfo);
                    dataCountTable = GetDistrictReportCount(districtId, reportId, startYear, startPeriod, endYear, endPeriod);
                    submissionTable = GetSubmittedDistrictReport(districtId, reportId, startYear, startPeriod, endYear, endPeriod);
                    missingTable = GetMissingDistrictReport(districtId, reportId, startYear, startPeriod, endYear, endPeriod);
                    break;

                case AccessLevel.FACILITY:
                    string facilityCode = accessLevelValue;
                    detailsTable = GetFacilityReport(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod, basicInfo);
                    dataCountTable = GetFacilityReportCount(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod);
                    submissionTable = GetSumittedFacilityReport(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod);
                    missingTable = GetMissingFacilityReport(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod);

                    if ((startYear == endYear) && (startPeriod == endPeriod) && (missingTable.Rows.Count == 0))
                    {
                        submissionInfoTable = GetReportSubmissionInfo(reportId, startYear, startPeriod, facilityCode);
                        submissionInfoTable.TableName = SUBMISSION_INFO_TABLE_NAME;
                        dataset.Tables.Add(submissionInfoTable);
                    }
                    break;
            }

            detailsTable.TableName = DETAILS_TABLE_NAME;
            dataCountTable.TableName = DATA_COUNT_TABLE_NAME;
            submissionTable.TableName = SUBMITTED_TABLE_NAME;
            missingTable.TableName = MISSING_TABLE_NAME;

            dataset.Tables.Add(detailsTable);
            dataset.Tables.Add(dataCountTable);
            dataset.Tables.Add(submissionTable);
            dataset.Tables.Add(missingTable);
            return dataset;
        }

        private static DataSet GetReportingInfo(AccessLevel accessLevel, string accessLevelValue, 
            int reportId, int startYear, int startPeriod, int endYear, int endPeriod, 
            int supportingPartnerId, bool basicInfo = false)
        {
            var dataset = new DataSet();
            DataTable detailsTable = null;
            DataTable dataCountTable = null;
            DataTable submissionTable = null;
            DataTable missingTable = null;
            DataTable submissionInfoTable = null;

            switch (accessLevel)
            {
                case AccessLevel.NATION:
                    detailsTable = GetNationReport(reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId, basicInfo);
                    dataCountTable = GetNationReportCount(reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    submissionTable = GetSubmittedNationReport(reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    missingTable = GetMissingNationReport(reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    break;

                case AccessLevel.REGION:
                    int regionId = int.Parse(accessLevelValue);
                    detailsTable = GetRegionReport(regionId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId, basicInfo);
                    dataCountTable = GetRegionReportCount(regionId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    submissionTable = GetSubmittedRegionReport(regionId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    missingTable = GetMissingRegionReport(regionId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    break;

                case AccessLevel.DISTRICT:
                    int districtId = int.Parse(accessLevelValue);
                    detailsTable = GetDistrictReport(districtId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId, basicInfo);
                    dataCountTable = GetDistrictReportCount(districtId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    submissionTable = GetSubmittedDistrictReport(districtId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    missingTable = GetMissingDistrictReport(districtId, reportId, startYear, startPeriod, endYear, endPeriod, supportingPartnerId);
                    break;

                case AccessLevel.FACILITY:
                    string facilityCode = accessLevelValue;
                    detailsTable = GetFacilityReport(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod, basicInfo);
                    dataCountTable = GetFacilityReportCount(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod);
                    submissionTable = GetSumittedFacilityReport(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod);
                    missingTable = GetMissingFacilityReport(facilityCode, reportId, startYear, startPeriod, endYear, endPeriod);

                    if ((startYear == endYear) && (startPeriod == endPeriod) && (missingTable.Rows.Count == 0))
                    {
                        submissionInfoTable = GetReportSubmissionInfo(reportId, startYear, startPeriod, facilityCode);
                        submissionInfoTable.TableName = SUBMISSION_INFO_TABLE_NAME;
                        dataset.Tables.Add(submissionInfoTable);
                    }
                    break;
            }

            detailsTable.TableName = DETAILS_TABLE_NAME;
            dataCountTable.TableName = DATA_COUNT_TABLE_NAME;
            submissionTable.TableName = SUBMITTED_TABLE_NAME;
            missingTable.TableName = MISSING_TABLE_NAME;

            dataset.Tables.Add(detailsTable);
            dataset.Tables.Add(dataCountTable);
            dataset.Tables.Add(submissionTable);
            dataset.Tables.Add(missingTable);
            return dataset;
        }

        #endregion

        public static DataTable GetReportSubmissionInfo(int reportID, int year, int period, string facilityCode)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    DbCommand command = null;
                    if (AppConfiguration.AccessMethod == DataAccessMethod.DIRECT_ACCESS)
                    {
                        command = GenericDataAccess.CreateCommand();
                    }
                    else
                    {
                        command = GenericDataAccess.CreateCacheDBCommand();
                    }
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT ReceivedSMS.SenderNum, ApprovedSMSCells.Name, 
                        ReceivedSMS.DateReceived FROM ReceivedSMS LEFT OUTER JOIN ApprovedSMSCells ON 
                        ReceivedSMS.SenderNum = ApprovedSMSCells.CellNum 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.FacCode = @FacCode) 
                        AND (ReceivedSMS.Year = @Year) AND (ReceivedSMS.Period = @Period)";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);                    

                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportSubmissionInfo(reportID, year, period, facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetAllReportYears()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllReportYears != null) return cache_AllReportYears;
            }
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DISTINCT Year FROM ReceivedSMS WHERE (Year BETWEEN 1990 AND 2050) ORDER BY Year";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ReportYear AS [Year] FROM ReportYears";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllReportYears();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_AllReportYears = dataTable;
            return dataTable;
        }

        public static DataTable GetAllReportPeriods()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllReportPeriods != null) return cache_AllReportPeriods;
            }

            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    string query = @"SELECT DISTINCT Period FROM ReceivedSMS WHERE (Period BETWEEN 1 AND 12) ORDER BY Period";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    dataTable = new DataTable();
                    DataColumn column = new DataColumn("Period", Type.GetType("System.Int32"));
                    dataTable.Columns.Add(column);
                    for (int i = 1; i <= 12; i++)
                    {
                        DataRow row = dataTable.NewRow();
                        row["Period"] = i;
                        dataTable.Rows.Add(row);
                    }
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllReportPeriods();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            
            
            if (AppConfiguration.DataCached) cache_AllReportPeriods = dataTable;
            return dataTable;
        }

        public static DataTable GetAllReportMonths()
        {
            DataTable dataTable = new DataTable();
            DataColumn column = new DataColumn("MonthName", Type.GetType("System.String"));
            dataTable.Columns.Add(column);
            column = new DataColumn("MonthValue", Type.GetType("System.Int32"));
            dataTable.Columns.Add(column);

            DataRow r = dataTable.NewRow();
            r[0] = "January";
            r[1] = 1;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "February";
            r[1] = 2;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "March";
            r[1] = 3;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "April";
            r[1] = 4;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "May";
            r[1] = 5;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "June";
            r[1] = 6;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "July";
            r[1] = 7;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "August";
            r[1] = 8;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "September";
            r[1] = 9;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "October";
            r[1] = 10;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "November";
            r[1] = 11;
            dataTable.Rows.Add(r);

            r = dataTable.NewRow();
            r[0] = "December";
            r[1] = 12;
            dataTable.Rows.Add(r);

            return dataTable;
        }
        #endregion

        #region Registered User Methods
        /// <summary>
        /// Returns DataTable object containing list of all registered user
        /// </summary>
        /// <returns>DataTable object</returns>
        public static DataTable GetRegisteredUsers()
        {
            // TODO: This method does not return all registered users instead SI registered users
            if (AppConfiguration.DataCached)
            {
                if (cache_RegisteredUsers != null) return cache_RegisteredUsers;
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ApprovedCellNo, CellNum, LTRIM(RTRIM(Name)) AS Name, LangID, SendSMS, 
                        FacCode FROM ApprovedSMSCells WHERE TitleID = 4 ORDER BY Name";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ApprovedCellNo, CellNum, [Name], LangID, SendSMS, 
                        FacCode FROM ApprovedSMSCells WHERE TitleID = 4 ORDER BY [Name]";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegisteredUsers();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_RegisteredUsers = dataTable;            
            return dataTable;
        }

        /// <summary>
        /// Get contact details of selected user identified by userID
        /// </summary>
        /// <param name="userID">Registered user id</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetRegisteredUserContacts(int userID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_RegisteredUserContacts.ContainsKey(userID))
                    return cache_RegisteredUserContacts[userID];
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT CellNum, Email FROM ApprovedSMSCells WHERE (ApprovedCellNo = @AssistantID)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@AssistantID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT CellNum, Email FROM ApprovedSMSCells WHERE (ApprovedCellNo = @AssistantID)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@AssistantID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegisteredUserContacts(userID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_RegisteredUserContacts[userID] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Saves the contacts of registered user identified by userID
        /// </summary>
        /// <param name="userID">Unique identifier of registered user</param>
        /// <param name="cellnum">Cell number</param>
        /// <param name="email">E-mail address</param>
        /// <returns>True if success otherwise false</returns>
        public static bool SaveRegisteredUserContacts(int userID, string cellnum, string email)
        {
            bool status = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string updateQuery = @"UPDATE ApprovedSMSCells SET CellNum=@CellNum, Email=@Email WHERE ApprovedCellNo=@UserID";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = updateQuery;
            
                    DbParameter parameter = command.CreateParameter();
                    parameter.ParameterName = "@UserID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userID;
                    command.Parameters.Add(parameter);

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@CellNum";
                    parameter.DbType = DbType.String;
                    parameter.Value = cellnum;
                    command.Parameters.Add(parameter);

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@Email";
                    parameter.DbType = DbType.String;
                    parameter.Value = email;
                    command.Parameters.Add(parameter);
                    int affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    status = (affectedRows > 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.UpdateRegisteredUserContacts(userID, cellnum, email);
                    output = DataTransformation.Decrypt(output);
                    status = bool.Parse(output);
                    break;
            }
            return status;
        }

        public static DataTable GetSMSUsers()
        {
            DataTable dataTable = null;
            DbCommand command = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT [ApprovedCellNo],[CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[UpdatedBy],[UpdateDate],[DeletedBy],
                        [DeleteDate],[Deleted] FROM [ApprovedSMSCells] WHERE [Deleted]<>1 OR (Deleted IS NULL)";
            
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT [ApprovedCellNo],[CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[UpdatedBy],[UpdateDate],[DeletedBy],
                        [DeleteDate],[Deleted] FROM [ApprovedSMSCells] WHERE [Deleted]<>1 OR (Deleted IS NULL)";
            
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllSMSUsers();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetSMSUser(int userId)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT [ApprovedCellNo],[CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[UpdatedBy],[UpdateDate],[DeletedBy],
                        [DeleteDate],[Deleted] FROM [ApprovedSMSCells] WHERE [ApprovedCellNo]=@UserId";

                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@UserId";
                    param.DbType = DbType.Int32;
                    param.Value = userId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT [ApprovedCellNo],[CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[UpdatedBy],[UpdateDate],[DeletedBy],
                        [DeleteDate],[Deleted] FROM [ApprovedSMSCells] 
                        WHERE [ApprovedCellNo]=@UserId";

                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@UserId";
                    param.DbType = DbType.Int32;
                    param.Value = userId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSMSUser(userId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetSMSUser(string phoneNumber)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT [ApprovedCellNo],[CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[UpdatedBy],[UpdateDate],[DeletedBy],
                        [DeleteDate],[Deleted] FROM [ApprovedSMSCells] WHERE [CellNum]=@CellNum";

                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT [ApprovedCellNo],[CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[UpdatedBy],[UpdateDate],[DeletedBy],
                        [DeleteDate],[Deleted] FROM [ApprovedSMSCells] 
                        WHERE [CellNum]=@CellNum";

                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSMSUserByPhoneNumber(phoneNumber);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static bool DeleteSMSUser(int userId, int actionUserId)
        {
            bool success = false;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"UPDATE [ApprovedSMSCells] SET [DeletedBy]=@DeletedBy,[DeleteDate]=@DeleteDate,
                        [Deleted]=1 FROM [ApprovedSMSCells] WHERE [ApprovedCellNo]=@UserId";
                    
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@DeletedBy";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@DeleteDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UserId";
                    param.DbType = DbType.Int32;
                    param.Value = userId;
                    command.Parameters.Add(param);
                    int affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    if (affectedRows == 1) success = true;
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"UPDATE [ApprovedSMSCells] SET [DeletedBy]=@DeletedBy,[DeleteDate]=@DeleteDate,
                        [Deleted]=1 FROM [ApprovedSMSCells] WHERE [ApprovedCellNo]=@UserId";

                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@DeletedBy";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@DeleteDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UserId";
                    param.DbType = DbType.Int32;
                    param.Value = userId;
                    command.Parameters.Add(param);
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    if (affectedRows == 1) success = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string sActionUserId = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.DeleteSMSUser(userId, sActionUserId);
                    output = DataTransformation.Decrypt(output);
                    success = Boolean.Parse(output);
                    break;
            }
            return success;
        }

        public static bool AddSMSUser(string phoneNumber, string fullname, int language, string facilityCode,
            string email, int title, int actionUserId)
        {
            bool success = false;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"INSERT INTO [ApprovedSMSCells] ([CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[Deleted]) VALUES(@CellNum,@Name,@LangID, @SendSMS,@FacCode,
                        @Email, @TitleID, @CreatedBy,@CreateDate,@Deleted)";

                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Name";
                    param.DbType = DbType.String;
                    param.Value = fullname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = language;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SendSMS";
                    param.DbType = DbType.Boolean;
                    param.Value = true;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Email";
                    param.DbType = DbType.String;
                    param.Value = email;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@TitleID";
                    param.DbType = DbType.Int32;
                    param.Value = title;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Deleted";
                    param.DbType = DbType.Boolean;
                    param.Value = false;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@CreatedBy";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@CreateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);
                    int affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    if (affectedRows == 1) success = true;
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"INSERT INTO [ApprovedSMSCells] ([CellNum],[Name],[LangID],[SendSMS],[FacCode],[Email],
                        [TitleID],[CreatedBy],[CreateDate],[Deleted]) VALUES(@CellNum,@Name,@LangID, @SendSMS,@FacCode,
                        @Email,@TitleID,@CreatedBy,@CreateDate,@Deleted)";

                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Name";
                    param.DbType = DbType.String;
                    param.Value = fullname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = language;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SendSMS";
                    param.DbType = DbType.Boolean;
                    param.Value = true;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Email";
                    param.DbType = DbType.String;
                    param.Value = email;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@TitleID";
                    param.DbType = DbType.Int32;
                    param.Value = title;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Deleted";
                    param.DbType = DbType.Boolean;
                    param.Value = false;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@CreatedBy";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@CreateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    if (affectedRows == 1) success = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.AddSMSUser2(phoneNumber, fullname, language, facilityCode,
                        email, title, userSignature);
                    output = DataTransformation.Decrypt(output);
                    success = Boolean.Parse(output);
                    break;
            }
            return success;
        }

        public static bool UpdateSMSUser(int userId, string phoneNumber, string fullname, int language, 
            string facilityCode, string email, int title,  int actionUserId)
        {
            bool success = false;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"UPDATE [ApprovedSMSCells] SET [CellNum]=@CellNum, [Name]=@Name, [LangID]=@LangID, 
                        [FacCode]=@FacCode, [Email]=@Email, [TitleID]=@TitleID, [UpdatedBy]=@UpdatedBy, 
                        [UpdateDate]=@UpdateDate WHERE [ApprovedCellNo]=@ApprovedCellNo";

                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Name";
                    param.DbType = DbType.String;
                    param.Value = fullname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = language;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Email";
                    param.DbType = DbType.String;
                    param.Value = email;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@TitleID";
                    param.DbType = DbType.Int32;
                    param.Value = title;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdatedBy";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userId;
                    command.Parameters.Add(param);
                    int affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    if (affectedRows == 1) success = true;
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"UPDATE [ApprovedSMSCells] SET [CellNum]=@CellNum, [Name]=@Name, [LangID]=@LangID, 
                        [FacCode]=@FacCode, [Email]=@Email, [TitleID]=@TitleID, [UpdatedBy]=@UpdatedBy, 
                        [UpdateDate]=@UpdateDate WHERE [ApprovedCellNo]=@ApprovedCellNo";

                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Name";
                    param.DbType = DbType.String;
                    param.Value = fullname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = language;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Email";
                    param.DbType = DbType.String;
                    param.Value = email;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@TitleID";
                    param.DbType = DbType.Int32;
                    param.Value = title;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdatedBy";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userId;
                    command.Parameters.Add(param);
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    if (affectedRows == 1) success = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.UpdatedSMSUser2(userId, phoneNumber, fullname, language, facilityCode, 
                        email, title, userSignature);
                    output = DataTransformation.Decrypt(output);
                    success = Boolean.Parse(output);
                    break;
            }
            return success;
        }

        #endregion

        #region Reports and Charts Methods
        /// <summary>
        /// Returns DataTable object that contains selected indicators for report identified by reportID
        /// </summary>
        /// <param name="reportID">Unique identifier of the report</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetReportIndicators(int reportID)
        {
            const string ANC_INDICATORS = @"SELECT DataDescription AS IndicatorName, DataPosition FROM ReportDataLocations
                                            WHERE (RepID = 2) AND (DataPosition IN (4, 5, 7, 8, 10, 11, 16, 17))";
            const string PCR_INDICATORS = @"SELECT DataDescription AS IndicatorName, DataPosition FROM ReportDataLocations
                                            WHERE (RepID = 3) AND (DataPosition IN (4, 11, 12, 13, 14))";
            const string MAT_INDICATORS = @"SELECT DataDescription AS IndicatorName, DataPosition FROM ReportDataLocations
                                            WHERE (RepID = 4) AND (DataPosition IN (4, 11, 12, 13, 14))";
            const string MC_INDICATORS = @"SELECT DataDescription AS IndicatorName, DataPosition FROM ReportDataLocations
                                            WHERE (RepID = 5) AND (DataPosition IN (4, 5, 11, 22))";
            string query = null;
            if (reportID == 2) query = ANC_INDICATORS;
            if (reportID == 3) query = PCR_INDICATORS;
            if (reportID == 4) query = MAT_INDICATORS;
            if (reportID == 5) query = MC_INDICATORS;

            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = System.Data.CommandType.Text;
            command.CommandText = query;
            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        public static DataTable GetChartIndicators(int chartID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ChartIndicators.ContainsKey(chartID))
                    return cache_ChartIndicators[chartID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT IndicatorID, ChartID, CompositeIndicator, IndicatorName, IndicatorDefinition
                        FROM PresetChartsIndicators WHERE (ChartID = @ChartID)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = query;
            
                    param = command.CreateParameter();
                    param.ParameterName = "@ChartID";
                    param.DbType = DbType.Int32;
                    param.Value = chartID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT IndicatorID, ChartID, CompositeIndicator, IndicatorName, IndicatorDefinition
                        FROM PresetChartsIndicators WHERE (ChartID = @ChartID)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = System.Data.CommandType.Text;
                    command.CommandText = query;
            
                    param = command.CreateParameter();
                    param.ParameterName = "@ChartID";
                    param.DbType = DbType.Int32;
                    param.Value = chartID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetChartIndicators(chartID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_ChartIndicators[chartID] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Gets all report expected from facility identified by facilityCode
        /// </summary>
        /// <param name="facilityCode">Unique identifier of Facility</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetFacilityExpectedReports(string facilityCode)
        {
            //if (AppConfiguration.DataCached)
            //{
            //    if (cache_ExpectedFacilityReports.ContainsKey(facilityCode))
            //        return cache_ExpectedFacilityReports[facilityCode];
            //}

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter parameter = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ReportID, ReportingStartDate, DirectEntry FROM ExpectedReports WHERE FacCode = @FacCode";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = facilityCode;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ReportID, ReportingStartDate, DirectEntry FROM ExpectedReports WHERE FacCode = @FacCode";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = facilityCode;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityExpectedReports(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            //if (AppConfiguration.DataCached) cache_ExpectedFacilityReports[facilityCode] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Gets all expected reports
        /// </summary>
        /// <returns>DataTable object</returns>
        public static DataTable GetAllExpectedReports()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ExpectedReports != null) return cache_ExpectedReports;
            }

            DataTable dataTable = null;
            string query = String.Empty;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT RepID, ReportName + ' [' + ISNULL(RepVersion,'...') + ']' AS [ReportName] 
                        FROM Report WHERE RepID < 9999 ORDER BY [ReportName] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT RepID, ReportName + ' [' + RepVersion + ']' AS [ReportName] 
                        FROM Report WHERE RepID < 9999 ORDER BY [ReportName] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllExpectedReports();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            
            
            if (dataTable.Rows.Count > 0) cache_ExpectedReports = dataTable;
            return dataTable;
        }

        public static DataTable GetAllExpectedReportViews()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ExpectedReportViews != null) return cache_ExpectedReportViews;
            }

            DataTable dataTable = null;
            string query = String.Empty;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT RepID, ReportName AS [ReportName] 
                        FROM Report WHERE UsedAsView = 1 ORDER BY [ReportName] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT RepID, ReportName AS [ReportName] 
                        FROM Report WHERE UsedAsView = 1 ORDER BY [ReportName] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllExpectedReportViews();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (dataTable.Rows.Count > 0) cache_ExpectedReportViews = dataTable;
            return dataTable;
        }

        public static DataTable GetFacilitiesDetailsByRegion(int regionID, bool basicInfo = false)
        {
            DataTable dataTable = null;
            string query = String.Empty;
            DbParameter parameter = null;
            DbCommand command = null;
            if (basicInfo)
            {
                query = @"SELECT Facilities.FacCode, Facilities.FacName, District.District, 
                    Region.RegionName, Facilities.SupportingPartnerId FROM (Facilities INNER JOIN Region ON 
                    Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                    Facilities.District = District.DistrictNo WHERE (Facilities.Region = @Region)
                    ORDER BY RegionName, District, FacName";
            }
            else
            {
                query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                    LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                    LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, 
                    ProphylaxisStartDate, ActiveDate, InactiveDate, Region.RegionName, Facilities.SupportingPartnerId 
                    FROM Facilities INNER JOIN Region ON Facilities.Region = Region.RegionNo WHERE Region = @Region
                    ORDER BY FacName";
            }

            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesByRegionID.ContainsKey(regionID))
                    return cache_FacilitiesByRegionID[regionID];
            }

            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@Region";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@Region";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilitiesDetailsByRegion2(regionID, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilitiesByRegionID[regionID] = dataTable;
            return dataTable;
        }

        public static DataTable GetFacilitiesDetailsByRegion(int regionID, int supportingPartnerId, bool basicInfo = false)
        {
            DataTable dataTable = null;
            string query = String.Empty;
            DbParameter parameter = null;
            DbCommand command = null;
            if (basicInfo)
            {
                query = @"SELECT Facilities.FacCode, Facilities.FacName, District.District, 
                    Region.RegionName FROM (Facilities INNER JOIN Region ON 
                    Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                    Facilities.District = District.DistrictNo 
                    WHERE (Facilities.Region = @Region) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)
                    ORDER BY RegionName, District, FacName";
            }
            else
            {
                query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                    LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                    LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, 
                    ProphylaxisStartDate, ActiveDate, InactiveDate, Region.RegionName 
                    FROM Facilities INNER JOIN Region ON Facilities.Region = Region.RegionNo 
                    WHERE (Region = @Region)  AND (Facilities.SupportingPartnerId = @SupportingPartnerId)
                    ORDER BY FacName";
            }

            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesByRegionID.ContainsKey(regionID))
                    return cache_FacilitiesByRegionID[regionID];
            }

            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@Region";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@SupportingPartnerId";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = supportingPartnerId;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@Region";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@SupportingPartnerId";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = supportingPartnerId;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilitiesDetailsByRegionBySupportingPartner(regionID, 
                        supportingPartnerId, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilitiesByRegionID[regionID] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Gets the details of facilities in district
        /// </summary>
        /// <param name="districtID">Unique identifier of district</param>
        /// <param name="useLocalDB">Determines whether the data is coming from the server or local cache</param>
        /// <param name="basicInfo">Determines if the data retrieved is basic or detailed</param>
        /// <returns></returns>
        public static DataTable GetFacilitiesDetailsByDistrict(int districtID, bool basicInfo = false)
        {
            DataTable dataTable = null;
            string query = String.Empty;
            DbCommand command = null;
            DbParameter parameter = null;
            if (basicInfo)
            {
                query = @"SELECT Facilities.FacCode, Facilities.FacName, District.District, 
                    Region.RegionName, Facilities.SupportingPartnerId FROM (Facilities INNER JOIN Region ON 
                    Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                    Facilities.District = District.DistrictNo 
                    WHERE (Facilities.District = @District) ORDER BY FacName ASC";
            }
            else
            {
                query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                    LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                    LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, 
                    ProphylaxisStartDate, ActiveDate, InactiveDate, Region.RegionName, SupportingPartnerId 
                    FROM Facilities INNER JOIN Region ON Facilities.Region = Region.RegionNo
                    WHERE District = @District ORDER BY FacName ASC";
            }

            //if (useLocalDB)
            //{ 
            //    command = GenericDataAccess.CreateCacheDBCommand();
            //    command.CommandType = CommandType.Text;
            //    command.CommandText = query;

            //    parameter = command.CreateParameter();
            //    parameter.ParameterName = "@District";
            //    parameter.DbType = DbType.Int32;
            //    parameter.Value = districtID;
            //    command.Parameters.Add(parameter);
            //    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            //    return dataTable;
            //}

            // From here on the info depends on the server
            if (AppConfiguration.DataCached)
            {
                if (basicInfo)
                {
                    if (cache_BasicInfoFacilitiesByDistrictID.ContainsKey(districtID))
                        return cache_BasicInfoFacilitiesByDistrictID[districtID];
                }
                else
                {
                    if (cache_FacilitiesByDistrictID.ContainsKey(districtID))
                        return cache_FacilitiesByDistrictID[districtID];
                }
            }
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@District";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
            
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@District";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilitiesDetailsByDistrict2(districtID, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached)
            {
                if (basicInfo) cache_BasicInfoFacilitiesByDistrictID[districtID] = dataTable;
                else cache_FacilitiesByDistrictID[districtID] = dataTable;
            }
            return dataTable;
        }

        public static DataTable GetFacilitiesDetailsByDistrict(int districtID, int supportingPartnerId, bool basicInfo = false)
        {
            DataTable dataTable = null;
            string query = String.Empty;
            DbCommand command = null;
            DbParameter parameter = null;
            if (basicInfo)
            {
                query = @"SELECT Facilities.FacCode, Facilities.FacName, District.District, 
                    Region.RegionName, Facilities.SupportingPartnerId FROM (Facilities INNER JOIN Region ON 
                    Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                    Facilities.District = District.DistrictNo 
                    WHERE (Facilities.District = @District) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)
                    ORDER BY FacName ASC";
            }
            else
            {
                query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                    LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                    LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, 
                    ProphylaxisStartDate, ActiveDate, InactiveDate, Region.RegionName, SupportingPartnerId 
                    FROM Facilities INNER JOIN Region ON Facilities.Region = Region.RegionNo
                    WHERE (District = @District) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)
                    ORDER BY FacName ASC";
            }

            // From here on the info depends on the server
            if (AppConfiguration.DataCached)
            {
                if (basicInfo)
                {
                    if (cache_BasicInfoFacilitiesByDistrictID.ContainsKey(districtID))
                        return cache_BasicInfoFacilitiesByDistrictID[districtID];
                }
                else
                {
                    if (cache_FacilitiesByDistrictID.ContainsKey(districtID))
                        return cache_FacilitiesByDistrictID[districtID];
                }
            }
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@District";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@SupportingPartnerId";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = supportingPartnerId;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@District";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);

                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@SupportingPartnerId";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = supportingPartnerId;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilitiesDetailsByDistrictBySupportingPartner(districtID, 
                        supportingPartnerId, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached)
            {
                if (basicInfo) cache_BasicInfoFacilitiesByDistrictID[districtID] = dataTable;
                else cache_FacilitiesByDistrictID[districtID] = dataTable;
            }
            return dataTable;
        }

        public static DataTable GetAllFacilitiesDetails(bool useLocalDB = false, bool basicInfo = false)
        {
            DataTable dataTable = null;
            string query = String.Empty;
            if (basicInfo)
            {
                query = @"SELECT Facilities.FacCode, Facilities.FacName, District.District, 
                    Region.RegionName FROM Facilities INNER JOIN Region ON 
                    Facilities.Region = Region.RegionNo INNER JOIN District ON 
                    Facilities.District = District.DistrictNo 
                    ORDER BY RegionName, District, FacName";
            }
            else
            {
                query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                    LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                    LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, 
                    ProphylaxisStartDate, ActiveDate, InactiveDate, Region.RegionName 
                    FROM Facilities INNER JOIN Region ON Facilities.Region = Region.RegionNo
                    ORDER BY RegionName, District, FacName";
            }

            // From here on the info depends on the server
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesDetails != null) return cache_FacilitiesDetails;
            }

            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesDetails(basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilitiesDetails = dataTable;
            return dataTable;
        }

        public static DataTable GetAllFacilitiesDetails(int supportingPartnerId, 
            bool useLocalDB = false, bool basicInfo = false)
        {
            DataTable dataTable = null;
            string query = String.Empty;
            if (basicInfo)
            {
                query = @"SELECT Facilities.FacCode, Facilities.FacName, District.District, 
                    Region.RegionName FROM Facilities INNER JOIN Region ON 
                    Facilities.Region = Region.RegionNo INNER JOIN District ON 
                    Facilities.District = District.DistrictNo 
                    WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                    ORDER BY RegionName, District, FacName";
            }
            else
            {
                query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT AS [PMTCTStatus],
                    LD AS [LDStatus], Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, 
                    LDStartDate, HEIDStartDate, ANCStartDate, ANC, HEID, Prophylaxis, 
                    ProphylaxisStartDate, ActiveDate, InactiveDate, Region.RegionName 
                    FROM Facilities INNER JOIN Region ON Facilities.Region = Region.RegionNo
                    WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                    ORDER BY RegionName, District, FacName";
            }

            // From here on the info depends on the server
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesDetails != null) return cache_FacilitiesDetails;
            }

            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;                    
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesDetailsBySupportingPartner(supportingPartnerId, basicInfo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilitiesDetails = dataTable;
            return dataTable;
        }

        public static DataTable GetAllFacilitiesDetails_Alpha()
        {
            DataTable dataTable = null;
            string query = @"SELECT Facilities.FacCode, Facilities.FacName, InternalName, FacilityType, 
                ProvideDBS, District.District, Region.RegionName FROM Facilities INNER JOIN Region ON 
                Facilities.Region = Region.RegionNo INNER JOIN District ON 
                Facilities.District = District.DistrictNo 
                ORDER BY RegionName, District, FacName";

            // From here on the info depends on the server
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesDetails != null) return cache_FacilitiesDetails;
            }

            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesDetails_Alpha();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilitiesDetails = dataTable;
            return dataTable;
        }

        public static DataTable GetAllFacilitiesDetailsByKnownSystem(int systemId)
        {
            DataTable dataTable = null;
            string query = @"SELECT OtherSystemsFacilityDetails.SystemId, 
                OtherSystemsFacilityDetails.InternalFacilityCode, OtherSystemsFacilityDetails.FacilityCode, 
                OtherSystemsFacilityDetails.FacilityName, Facilities.FacName AS InternalFacilityName, 
                Facilities.FacilityType, Facilities.ProvideDBS, OtherSystemsFacilityDetails.DistrictName, 
                OtherSystemsFacilityDetails.RegionName, Region.RegionName AS InternalRegionName, 
                District.District AS InternalDistrictName

                FROM OtherSystemsFacilityDetails INNER JOIN 
                Facilities ON OtherSystemsFacilityDetails.InternalFacilityCode = Facilities.FacCode
                INNER JOIN Region ON Facilities.Region = Region.RegionNo 
                INNER JOIN District ON Facilities.District = District.DistrictNo

                WHERE (OtherSystemsFacilityDetails.SystemId = @SystemId) 
                ORDER BY OtherSystemsFacilityDetails.RegionName, 
                OtherSystemsFacilityDetails.DistrictName, OtherSystemsFacilityDetails.FacilityName";
            
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@SystemId";
                    param.DbType = DbType.Int32;
                    param.Value = systemId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@SystemId";
                    param.DbType = DbType.Int32;
                    param.Value = systemId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesDetailsByKnownSystem(systemId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }









        public static List<DataModels.ModelViews.OtherSystemsFacilityDetailView> GetOtherSystemsFacilityDetails(int systemId)
        {
            List<DataModels.ModelViews.OtherSystemsFacilityDetailView> systemDetails = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        //db.Configuration.LazyLoadingEnabled = false;
                        //db.Configuration.ProxyCreationEnabled = false;

                        var results = from s in db.OtherSystemsFacilityDetails
                                      //.Include("Facility")
                                      //.Include("Facility.Region")
                                      //.Include("Facility.District")
                                      where s.SystemId == systemId
                                      select new DataModels.ModelViews.OtherSystemsFacilityDetailView
                                      {
                                          SystemId = s.SystemId,
                                          FacilityCode = s.FacilityCode,
                                          FacilityName = s.FacilityName,
                                          DistrictName = s.DistrictName,
                                          RegionName = s.RegionName,

                                          InternalFacilityCode = s.InternalFacilityCode,
                                          InternalFacilityName = s.Facility.FacName,
                                          InternalDistrictName = s.Facility.District.District1,
                                          InternalRegionName = s.Facility.District.Region.RegionName,

                                          FacilityType = s.Facility.FacilityTypeId,
                                          ProvideDBS = s.Facility.ProvideDBS,

                                          HTC_ServiceType = s.HTC_ServiceType,
                                          Care_ServiceType = s.Care_ServiceType,
                                          FN_ServiceType = s.FN_ServiceType,
                                          TB_HIV_ServiceType = s.TB_HIV_ServiceType,
                                          TX_ServiceType = s.TX_ServiceType,
                                          PMTCT_ServiceType = s.PMTCT_ServiceType,
                                          HRH_ServiceType = s.HRH_ServiceType,
                                          LAB_ServiceType = s.LAB_ServiceType,
                                          VMMC_ServiceType = s.VMMC_ServiceType,
                                          GPY_ServiceType = s.GPY_ServiceType,
                                          KP_ServiceType = s.KP_ServiceType,
                                          OVC_ServiceType = s.OVC_ServiceType,
                                          FPINT_ServiceType = s.FPINT_ServiceType
                                      };

                        systemDetails = results.ToList();
                        return systemDetails;
                    }

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new Exception("MS Access database back-end is not supported");

                case DataAccessMethod.WEB_SERVICES:
                    var output = webService.GetKnownSystemsFacilityDetails(systemId);
                    systemDetails = DataModels.Services.Deserialize(output, typeof(List<DataModels.ModelViews.OtherSystemsFacilityDetailView>))
                        as List<DataModels.ModelViews.OtherSystemsFacilityDetailView>;
                    break;
            }
            return systemDetails;
        }

        public static DataModels.ModelViews.OtherSystemsFacilityDetailView GetOtherSystemsFacilityDetails(int systemId, string internalFacilityCode)
        {
            DataModels.ModelViews.OtherSystemsFacilityDetailView systemDetails = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        //db.Configuration.LazyLoadingEnabled = false;
                        //db.Configuration.ProxyCreationEnabled = false;

                        var results = (from s in db.OtherSystemsFacilityDetails
                                          //.Include("Facility")
                                          //.Include("Facility.Region")
                                          //.Include("Facility.District")
                                      where s.SystemId == systemId && s.InternalFacilityCode == internalFacilityCode
                                      select new DataModels.ModelViews.OtherSystemsFacilityDetailView
                                      {
                                          SystemId = s.SystemId,
                                          FacilityCode = s.FacilityCode,
                                          FacilityName = s.FacilityName,
                                          DistrictName = s.DistrictName,
                                          RegionName = s.RegionName,
                                          
                                          InternalFacilityCode = s.InternalFacilityCode,
                                          InternalFacilityName = s.Facility.FacName,
                                          InternalDistrictName = s.Facility.District.District1,
                                          InternalRegionName = s.Facility.District.Region.RegionName,
                                          
                                          FacilityType = s.Facility.FacilityTypeId,
                                          ProvideDBS = s.Facility.ProvideDBS,

                                          HTC_ServiceType = s.HTC_ServiceType,
                                          Care_ServiceType = s.Care_ServiceType,
                                          FN_ServiceType = s.FN_ServiceType,
                                          TB_HIV_ServiceType = s.TB_HIV_ServiceType,
                                          TX_ServiceType = s.TX_ServiceType,
                                          PMTCT_ServiceType = s.PMTCT_ServiceType,
                                          HRH_ServiceType = s.HRH_ServiceType,
                                          LAB_ServiceType = s.LAB_ServiceType,
                                          VMMC_ServiceType = s.VMMC_ServiceType,
                                          GPY_ServiceType = s.GPY_ServiceType,
                                          KP_ServiceType = s.KP_ServiceType,
                                          OVC_ServiceType = s.OVC_ServiceType,
                                          FPINT_ServiceType = s.FPINT_ServiceType
                                      }).FirstOrDefault();

                        return results;
                    }

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new Exception("MS Access database back-end is not supported");

                case DataAccessMethod.WEB_SERVICES:
                    var output = webService.GetKnownSystemsFacilityDetail(systemId, internalFacilityCode);
                    systemDetails = DataModels.Services.Deserialize(output, typeof(DataModels.ModelViews.OtherSystemsFacilityDetailView)) 
                        as DataModels.ModelViews.OtherSystemsFacilityDetailView;
                    break;
            }
            return systemDetails;
        }

        public static List<DataModels.Models.OtherSystemsDistrictDetail> GetOtherSystemsDistrictDetails(int systemId)
        {
            List<DataModels.Models.OtherSystemsDistrictDetail> systemDetails = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        //db.Configuration.LazyLoadingEnabled = false;
                        //db.Configuration.ProxyCreationEnabled = false;

                        var results = from s in db.OtherSystemsDistrictDetails
                                      //.Include("Facility")
                                      //.Include("Facility.Region")
                                      //.Include("Facility.District")
                                      where s.SystemId == systemId
                                      select s;

                        systemDetails = results.ToList();
                        return systemDetails;
                    }

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new Exception("MS Access database back-end is not supported");

                case DataAccessMethod.WEB_SERVICES:
                    var output = webService.GetKnownSystemsDistrictDetails(systemId);
                    systemDetails = DataModels.Services.Deserialize(output, typeof(List<DataModels.Models.OtherSystemsDistrictDetail>))
                        as List<DataModels.Models.OtherSystemsDistrictDetail>;
                    break;
            }
            return systemDetails;
        }

        public static DataModels.Models.OtherSystemsDistrictDetail GetOtherSystemsDistrictDetails(int systemId, int internalDistrictId)
        {
            DataModels.Models.OtherSystemsDistrictDetail systemDetails = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        //db.Configuration.LazyLoadingEnabled = false;
                        //db.Configuration.ProxyCreationEnabled = false;

                        var results = (from s in db.OtherSystemsDistrictDetails
                                      //.Include("Facility")
                                      //.Include("Facility.Region")
                                      //.Include("Facility.District")
                                      where s.SystemId == systemId && s.InternalDistrictId == internalDistrictId
                                      select s).FirstOrDefault();

                        return results;
                    }

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new Exception("MS Access database back-end is not supported");

                case DataAccessMethod.WEB_SERVICES:
                    var output = webService.GetKnownSystemsDistrictDetail(systemId, internalDistrictId);
                    systemDetails = DataModels.Services.Deserialize(output, typeof(DataModels.Models.OtherSystemsDistrictDetail))
                        as DataModels.Models.OtherSystemsDistrictDetail;
                    break;
            }
            return systemDetails;
        }

        public static List<DataModels.Models.OtherSystemsRegionDetail> GetOtherSystemsRegionDetails(int systemId)
        {
            List<DataModels.Models.OtherSystemsRegionDetail> systemDetails = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        //db.Configuration.LazyLoadingEnabled = false;
                        //db.Configuration.ProxyCreationEnabled = false;

                        var results = from s in db.OtherSystemsRegionDetails
                                      where s.SystemId == systemId
                                      select s;

                        systemDetails = results.ToList();
                        return systemDetails;
                    }

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new Exception("MS Access database back-end is not supported");

                case DataAccessMethod.WEB_SERVICES:
                    var output = webService.GetKnownSystemsRegionDetails(systemId);
                    systemDetails = DataModels.Services.Deserialize(output, typeof(List<DataModels.Models.OtherSystemsRegionDetail>))
                        as List<DataModels.Models.OtherSystemsRegionDetail>;
                    break;
            }
            return systemDetails;
        }

        public static DataModels.Models.OtherSystemsRegionDetail GetOtherSystemsRegionDetails(int systemId, int internalRegionId)
        {
            DataModels.Models.OtherSystemsRegionDetail systemDetails = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        //db.Configuration.LazyLoadingEnabled = false;
                        //db.Configuration.ProxyCreationEnabled = false;

                        var results = (from s in db.OtherSystemsRegionDetails
                                      where s.SystemId == systemId && s.InternalRegionId == internalRegionId
                                      select s).FirstOrDefault();

                        return results;
                    }

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new Exception("MS Access database back-end is not supported");

                case DataAccessMethod.WEB_SERVICES:
                    var output = webService.GetKnownSystemsRegionDetail(systemId, internalRegionId);
                    systemDetails = DataModels.Services.Deserialize(output, typeof(DataModels.Models.OtherSystemsRegionDetail))
                        as DataModels.Models.OtherSystemsRegionDetail;
                    break;
            }
            return systemDetails;
        }














        public static DataTable GetAllFacilitiesDetails_Alpha(int supportingPartnerId)
        {
            DataTable dataTable = null;
            string query = @"SELECT Facilities.FacCode, Facilities.FacName, InternalName, FacilityType, 
                ProvideDBS, District.District, Region.RegionName FROM Facilities INNER JOIN Region ON 
                Facilities.Region = Region.RegionNo INNER JOIN District ON 
                Facilities.District = District.DistrictNo 
                WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId)
                ORDER BY RegionName, District, FacName";

            // From here on the info depends on the server
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesDetails != null) return cache_FacilitiesDetails;
            }

            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesDetails_AlphaBySupportingPartner(supportingPartnerId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilitiesDetails = dataTable;
            return dataTable;
        }

        public static DataTable GetAllExpectedCharts()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ExpectedCharts != null) return cache_ExpectedCharts;
            }

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ChartID, ChartName FROM PresetCharts ORDER BY ChartName ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;
                    
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ChartID, ChartName FROM PresetCharts ORDER BY ChartName ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllExpectedCharts();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_ExpectedCharts = dataTable;
            return dataTable;
        }        

        public static DataTable GetFacilitiesWithoutReport(int reportID, int period, int year)
        {
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name] 
                        FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode 
                        WHERE (Facilities.Activated = 1) AND (Facilities.FacCode NOT IN (SELECT DISTINCT ExpectedReports_1.FacCode FROM ExpectedReports 
                        AS ExpectedReports_1 INNER JOIN ReceivedSMS ON ExpectedReports_1.FacCode = ReceivedSMS.FacCode 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.Period = @Period) AND (ReceivedSMS.Year = @Year))) 
                        AND (ExpectedReports.ReportID = @RepID) ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name] 
                        FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode 
                        WHERE (Facilities.Activated = 1) AND (Facilities.FacCode NOT IN (SELECT DISTINCT ExpectedReports_1.FacCode FROM ExpectedReports 
                        AS ExpectedReports_1 INNER JOIN ReceivedSMS ON ExpectedReports_1.FacCode = ReceivedSMS.FacCode 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.Period = @Period) AND (ReceivedSMS.Year = @Year))) 
                        AND (ExpectedReports.ReportID = @RepID) ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilitiesWithoutReport(reportID, period, year);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            
            return dataTable;
        }

        public static DataTable GetDistrictFacilitiesWithoutReport(int districtID, int reportID, int period, int year)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name] 
                        FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode 
                        WHERE (Facilities.Activated = 1) AND  (Facilities.FacCode NOT IN (SELECT DISTINCT ExpectedReports_1.FacCode FROM ExpectedReports 
                        AS ExpectedReports_1 INNER JOIN ReceivedSMS ON ExpectedReports_1.FacCode = ReceivedSMS.FacCode 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.Period = @Period) AND (ReceivedSMS.Year = @Year))) 
                        AND (ExpectedReports.ReportID = @RepID) AND (Facilities.District=@DistrictID)
                        ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name] 
                        FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode 
                        WHERE (Facilities.Activated = 1) AND (Facilities.FacCode NOT IN (SELECT DISTINCT ExpectedReports_1.FacCode FROM ExpectedReports 
                        AS ExpectedReports_1 INNER JOIN ReceivedSMS ON ExpectedReports_1.FacCode = ReceivedSMS.FacCode 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.Period = @Period) AND (ReceivedSMS.Year = @Year))) 
                        AND (ExpectedReports.ReportID = @RepID) AND (Facilities.District=@DistrictID)
                        ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictFacilitiesWithoutReport(districtID, reportID, period, year);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetRegionFacilitiesWithoutReport(int regionID, int reportID, int period, int year)
        {
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name] 
                        FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode 
                        WHERE (Facilities.Activated = 1) AND (Facilities.FacCode NOT IN (SELECT DISTINCT ExpectedReports_1.FacCode FROM ExpectedReports 
                        AS ExpectedReports_1 INNER JOIN ReceivedSMS ON ExpectedReports_1.FacCode = ReceivedSMS.FacCode 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.Period = @Period) AND (ReceivedSMS.Year = @Year))) 
                        AND (ExpectedReports.ReportID = @RepID) AND (Facilities.Region=@RegionID)
                        ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RegionID";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name] 
                        FROM Facilities INNER JOIN ExpectedReports ON Facilities.FacCode = ExpectedReports.FacCode 
                        WHERE (Facilities.Activated = 1) AND (Facilities.FacCode NOT IN (SELECT DISTINCT ExpectedReports_1.FacCode FROM ExpectedReports 
                        AS ExpectedReports_1 INNER JOIN ReceivedSMS ON ExpectedReports_1.FacCode = ReceivedSMS.FacCode 
                        WHERE (ReceivedSMS.RepID = @RepID) AND (ReceivedSMS.Period = @Period) AND (ReceivedSMS.Year = @Year))) 
                        AND (ExpectedReports.ReportID = @RepID) AND (Facilities.Region=@RegionID)
                        ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RegionID";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegionFacilitiesWithoutReport(regionID, reportID, period, year);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }
        
        public static string GetPartialFacilityName(string partialFacilityCode)
        {
            int length = partialFacilityCode.Length;
            string query = String.Empty;
            switch(length)
            {
                case 8: // Probably facility code
                    query = @"SELECT [FacName] FROM [Facilities] WHERE [FacCode]=@Code";
                    break;

                case 4: // Probably district code
                    query = @"SELECT TOP (1) District.District FROM Facilities INNER JOIN District 
                        ON Facilities.District = District.DistrictNo WHERE (Facilities.FacCode LIKE @Code + '%')";
                    break;

                case 2: // Probably region code
                    query = @"SELECT TOP (1) Region.RegionName FROM Facilities INNER JOIN Region 
                        ON Facilities.Region = Region.RegionNo WHERE (Facilities.FacCode LIKE @Code + '%')";
                    break;

                default:
                    query =  String.Empty;
                    break;
            }
            if (String.IsNullOrEmpty(query)) return String.Empty;

            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = query;
            
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@Code";
            param.DbType = DbType.String;
            param.Value = partialFacilityCode;
            command.Parameters.Add(param);

            string output = GenericDataAccess.ExecuteScalar(command);
            return output;
        }

        public static DataTable GetReportAllDataDescriptions(int reportID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ReportDataDescriptions.ContainsKey(reportID))
                    return cache_ReportDataDescriptions[reportID];
            }

            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT rd.ShortCode, rd.DataDescription, rd.DataType, 
                        rd.DataPosition AS DataPosition FROM ReportDataLocations AS rd 
                        WHERE rd.RepID = @ReportID ORDER BY Dataposition";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@ReportID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportAllDataDescriptions(reportID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_ReportDataDescriptions[reportID] = dataTable;
            return dataTable;
        }

        public static DataTable GetReportDetails(int reportID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ReportDetails.ContainsKey(reportID)) return cache_ReportDetails[reportID];
            }

            DataTable dataTable = null;
            DbParameter param = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT RepID, ReportName, RepVersion FROM Report WHERE RepID=@RepID";
            
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT RepID, ReportName, RepVersion FROM Report WHERE RepID=@RepID";
            
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportDetails(reportID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_ReportDetails[reportID] = dataTable;
            return dataTable;
        }        

        #region Donor Report
        public static DataTable GetReportDataTable(ReportLevel level, object levelID, DonorReportParts part, 
            DateTime startingDateTime, DateTime endingDateTime)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    #region All Nation Report Queries
                    const string ANC_REPORT_BY_NATION_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 6) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 6) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod AND @EndPeriod)
                    GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";

                    const string MAT_REPORT_BY_NATION_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 7) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 7) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod AND @EndPeriod)
                    GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";

                    const string MC_REPORT_BY_NATION_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 9) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 9) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod AND @EndPeriod)
                    GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";
                    #endregion

                    #region All Regions Report Queries
                    const string ANC_REPORT_BY_REGION_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 6) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 6) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod AND @EndPeriod) AND (RegionID = @RegionID)
                    GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";

                    const string MAT_REPORT_BY_REGION_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 7) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 7) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod AND @EndPeriod) AND (RegionID = @RegionID)
                    GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";

                    const string MC_REPORT_BY_REGION_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 9) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 9) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod AND @EndPeriod) AND (RegionID = @RegionID)
                    GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";
                    #endregion

                    #region All Districts Report Queries
                    const string ANC_REPORT_BY_DISTRICT_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 6) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 6) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod 
                    AND @EndPeriod) AND (DistrictID = @DistrictID) GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";

                    const string MAT_REPORT_BY_DISTRICT_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 7) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 7) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod 
                    AND @EndPeriod) AND (DistrictID = @DistrictID) GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";

                    const string MC_REPORT_BY_DISTRICT_QUERY = @"SELECT Indicator.Indicator, ISNULL(ReportData.Data,0)
                    FROM (SELECT SUBSTRING(DataDescription, 1, 6) AS Indicator, DataPosition
                    FROM  ReportDataLocations
                    WHERE (RepID = 9) AND (DataPosition > 2)) AS Indicator LEFT OUTER JOIN
                    (SELECT TOP (100) PERCENT SUM(CAST(ReportData AS INT)) AS Data, ReportDataPosition
                    FROM FacilitiesReports
                    WHERE (ReportID = 9) AND (Year BETWEEN @StartYear AND @EndYear) AND (Month BETWEEN @StartPeriod 
                    AND @EndPeriod) AND (DistrictID = @DistrictID) GROUP BY ReportDataPosition
                    ORDER BY ReportDataPosition) AS ReportData ON Indicator.DataPosition = ReportData.ReportDataPosition";
                    #endregion

                    string query = String.Empty;
                    string levelIDParameterName = String.Empty;
                    
                    #region Determining query and level
                    switch (part)
                    {
                        case DonorReportParts.ANC:                            
                            if (level == ReportLevel.NATION)
                            {
                                query = ANC_REPORT_BY_NATION_QUERY;
                                levelIDParameterName = null;
                                break;
                            }
                            if (level == ReportLevel.REGION)
                            {
                                query = ANC_REPORT_BY_REGION_QUERY;
                                levelIDParameterName = "@RegionID";
                                break;
                            }
                            if (level == ReportLevel.DISTRICT)
                            {
                                query = ANC_REPORT_BY_DISTRICT_QUERY;
                                levelIDParameterName = "@DistrictID";
                                break;
                            }
                            break;

                        case DonorReportParts.MAT:
                            if (level == ReportLevel.NATION)
                            {
                                query = MAT_REPORT_BY_NATION_QUERY;
                                levelIDParameterName = null;
                                break;
                            }
                            if (level == ReportLevel.REGION)
                            {
                                query = MAT_REPORT_BY_REGION_QUERY;
                                levelIDParameterName = "@RegionID";
                                break;
                            }
                            if (level == ReportLevel.DISTRICT)
                            {
                                query = MAT_REPORT_BY_DISTRICT_QUERY;
                                levelIDParameterName = "@DistrictID";
                                break;
                            }
                            break;

                        case DonorReportParts.MC:
                            if (level == ReportLevel.NATION)
                            {
                                query = MC_REPORT_BY_NATION_QUERY;
                                levelIDParameterName = null;
                                break;
                            }
                            if (level == ReportLevel.REGION)
                            {
                                query = MC_REPORT_BY_REGION_QUERY;
                                levelIDParameterName = "@RegionID";
                                break;
                            }
                            if (level == ReportLevel.DISTRICT)
                            {
                                query = MC_REPORT_BY_DISTRICT_QUERY;
                                levelIDParameterName = "@DistrictID";
                                break;
                            }
                            break;
                    }
                    #endregion

                    #region Running Select Command
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@StartYear";
                    param.DbType = DbType.Int32;
                    param.Value = startingDateTime.Year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@EndYear";
                    param.DbType = DbType.Int32;
                    param.Value = endingDateTime.Year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@StartPeriod";
                    param.DbType = DbType.Int32;
                    param.Value = startingDateTime.Month;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@EndPeriod";
                    param.DbType = DbType.Int32;
                    param.Value = endingDateTime.Month;
                    command.Parameters.Add(param);

                    if (!String.IsNullOrEmpty(levelIDParameterName))
                    {
                        param = command.CreateParameter();
                        param.ParameterName = levelIDParameterName;
                        param.DbType = DbType.String;
                        param.Value = levelID;
                        command.Parameters.Add(param);
                    }
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    #endregion
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    IQServices.ReportLevel iLevel = IQServices.ReportLevel.NATION;
                    if (level == ReportLevel.REGION) iLevel = IQServices.ReportLevel.REGION;
                    if (level == ReportLevel.DISTRICT) iLevel = IQServices.ReportLevel.DISTRICT;

                    IQServices.DonorReportParts iPart = IQServices.DonorReportParts.ANC;
                    if (part == DonorReportParts.MAT) iPart = IQServices.DonorReportParts.MAT;
                    if (part == DonorReportParts.MC) iPart = IQServices.DonorReportParts.MC;

                    string output = webService.DonorReportGetReportDataTable(iLevel, levelID, iPart, startingDateTime, endingDateTime);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            
            return dataTable;
        }
        #endregion

        #region Charts
        private static int EvaluateIndicator(ReportLevel level, string indicator, 
            DateTime startDate, DateTime endDate, object ID)
        {
            string[] parts = indicator.Split('.');
            int reportID = int.Parse(parts[0]);
            int dataPosition = int.Parse(parts[1]);

            int startYear = startDate.Year;
            int endYear = endDate.Year;
            int startPeriod = startDate.Month;
            int endPeriod = endDate.Month;
            int data = 0;

            if (startYear == endYear)
            {
                data = EvaluateIndicator(level, reportID, dataPosition, startYear, startPeriod, endPeriod, ID);
            }
            else
            {
                int currentYear = startYear;
                do
                {
                    int startingPeriod = 1;
                    int endingPeriod = 12;
                    if (currentYear == startYear) startingPeriod = startPeriod;
                    if (currentYear == endYear) endingPeriod = endPeriod;

                    data += EvaluateIndicator(level, reportID, dataPosition, currentYear, startPeriod, endPeriod, ID);
                    currentYear++;
                } while (currentYear <= endYear);
            }
            return data;
        }

        //TODO: This method needs review to deal with Supporting Partner idea
        private static int EvaluateIndicator(ReportLevel level, int reportID, 
            int dataPosition, int year, int startPeriod, int endPeriod, object ID)
        {
            string query = null;

            DbParameter param = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    break;
            }
            command.CommandType = CommandType.Text;
            switch (level)
            {
                case ReportLevel.NATION:
                    if (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DATA_ACCESS)
                    {
                        query = @"SELECT SUM(ReportData.Data) AS ReportData FROM ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo WHERE     
                        (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition)";
                    }
                    else
                    {
                        query = @"SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo WHERE     
                        (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition)";
                    }               
                    command.CommandText = query;
                    break;

                case ReportLevel.REGION:
                    if (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DATA_ACCESS)
                    {
                        query = @"SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                        Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE (Facilities.Region = @RegionID)
                        AND (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition)";
                    }
                    else
                    {
                        query = @"SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                        Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                        (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition) AND (Facilities.Region = @RegionID)";
                    }
                    
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@RegionID";
                    param.DbType = DbType.Int32;
                    param.Value = ID;
                    command.Parameters.Add(param);
                    break;

                case ReportLevel.DISTRICT:
                    if (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DATA_ACCESS)
                    {
                        query = @"SELECT SUM(ReportData.Data) AS ReportData FROM (ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo) INNER JOIN
                        Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE (Facilities.District = @DistrictID)
                        AND (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition)";
                    }
                    else
                    {
                        query = @"SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo INNER JOIN
                        Facilities ON ReceivedSMS.FacCode = Facilities.FacCode WHERE 
                        (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition) AND (Facilities.District = @DistrictID)";
                    }
                    
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = ID;
                    command.Parameters.Add(param);
                    break;

                case ReportLevel.FACILITY:
                    if (AppConfiguration.AccessMethod == DataAccessMethod.OFFLINE_DATA_ACCESS)
                    {
                        query = @"SELECT SUM(ReportData.Data) AS ReportData FROM ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo WHERE     
                        (ReceivedSMS.FacCode = @FacilityCode) AND (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition)";
                    }
                    else
                    {
                        query = @"SELECT ISNULL(SUM(CAST(ReportData.Data AS INT)), 0) AS ReportData FROM ReportData 
                        INNER JOIN ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo WHERE     
                        (ReceivedSMS.Year = @Year) AND 
                        (ReceivedSMS.Period BETWEEN @StartPeriod AND @EndPeriod) AND (ReportData.RepID = @ReportID) AND 
                        (ReportData.DataPosition = @DataPosition) AND (ReceivedSMS.FacCode = @FacilityCode)";
                    }
                    
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = ID;
                    command.Parameters.Add(param);
                    break;
            }

            #region Filling Command Parameters
            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@StartPeriod";
            param.DbType = DbType.Int32;
            param.Value = startPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@EndPeriod";
            param.DbType = DbType.Int32;
            param.Value = endPeriod;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@DataPosition";
            param.DbType = DbType.Int32;
            param.Value = dataPosition;
            command.Parameters.Add(param);
            #endregion

            string output = GenericDataAccess.ExecuteScalar(command);
            int data = int.Parse(output);
            return data;
        }

        public static DataTable GetChartData(ReportLevel level, object levelID, int startYear, int startPeriod,
            int endYear, int endPeriod, List<ChartIndicatorInfo> reportIndicators)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    dataTable = new DataTable();
                    DataColumn column = new DataColumn("Measure", Type.GetType("System.String"));
                    dataTable.Columns.Add(column);
                    column = new DataColumn("Data", Type.GetType("System.Int32"));
                    dataTable.Columns.Add(column);

                    DateTime startDate = DateTime.Parse(String.Format("{0}-{1}-01", startYear, startPeriod));
                    DateTime endDate = DateTime.Parse(String.Format("{0}-{1}-01", endYear, endPeriod));
                    #region Populating table data
                    foreach (ChartIndicatorInfo indicator in reportIndicators)
                    {
                        int data = 0;
                        if (indicator.IsComposite)
                        {
                            ArithmeticOperation operation = ArithmeticOperation.ADD;
                            // Try to split the definition
                            string[] parts = indicator.IndicatorDefinition.Split(' ');
                            foreach (string part in parts)
                            {
                                if (part.Contains("."))
                                {
                                    #region Process Data
                                    int value = Utilities.EvaluateIndicator(level, part, startDate, endDate, levelID);
                                    switch (operation)
                                    {
                                        case ArithmeticOperation.ADD:
                                            data = data + value;
                                            break;

                                        case ArithmeticOperation.SUBTRACT:
                                            data = data - value;
                                            break;

                                        case ArithmeticOperation.MULTIPLY:
                                            data = data * value;
                                            break;

                                        case ArithmeticOperation.DIVIDE:
                                            data = data / value;
                                            break;
                                    }
                                    #endregion
                                }
                                else
                                {
                                    #region Operator
                                    switch (part)
                                    {
                                        case "+":
                                            operation = ArithmeticOperation.ADD;
                                            break;

                                        case "-":
                                            operation = ArithmeticOperation.SUBTRACT;
                                            break;

                                        case "*":
                                            operation = ArithmeticOperation.MULTIPLY;
                                            break;

                                        case "/":
                                            operation = ArithmeticOperation.DIVIDE;
                                            break;
                                    }
                                    #endregion
                                }
                            }
                        }
                        else
                        {
                            data = Utilities.EvaluateIndicator(level, indicator.IndicatorDefinition, startDate, endDate, levelID);
                        }

                        // Adding data to the table
                        DataRow row = dataTable.NewRow();
                        row["Measure"] = indicator.IndicatorName;
                        row["Data"] = data;
                        dataTable.Rows.Add(row);
                    }
                    #endregion
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    IQServices.ReportLevel iLevel = IQServices.ReportLevel.NATION;
                    if (level == ReportLevel.REGION) iLevel = IQServices.ReportLevel.REGION;
                    if (level == ReportLevel.DISTRICT) iLevel = IQServices.ReportLevel.DISTRICT;
                    if (level == ReportLevel.FACILITY) iLevel = IQServices.ReportLevel.FACILITY;

                    IQServices.ChartIndicatorInfo[] iReportIndicators = new IQServices.ChartIndicatorInfo[reportIndicators.Count];
                    for (int i = 0; i < reportIndicators.Count; i++)
                    {
                        ChartIndicatorInfo info = reportIndicators[i];
                        IQServices.ChartIndicatorInfo chartInfo = new IQServices.ChartIndicatorInfo();
                        
                        chartInfo.ChartID = info.ChartID;
                        chartInfo.IndicatorDefinition = info.IndicatorDefinition;
                        chartInfo.IndicatorID = info.IndicatorID;
                        chartInfo.IndicatorName = info.IndicatorName;
                        chartInfo.IsComposite = info.IsComposite;
                        
                        iReportIndicators[i] = chartInfo;
                    }

                    string output = webService.GetChartData(iLevel, levelID, startYear, startPeriod, 
                        endYear, endPeriod, iReportIndicators);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }            
            return dataTable;
        }
        #endregion

        #region Report Management
        public static bool CreateReport(string name, string repVersion, int dataCount, 
            string description, string comments, bool usedAsView, int actionUserId)
        {
            bool status = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"INSERT INTO Report (ReportName, RepVersion, Description, Comments, UsedAsView) 
                        VALUES (@ReportName, @RepVersion, @Description, @Comments, @UsedAsView)";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@ReportName";
                    param.DbType = DbType.String;
                    param.Value = name;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RepVersion";
                    param.DbType = DbType.String;
                    param.Value = repVersion;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Description";
                    param.DbType = DbType.String;
                    param.Value = description;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Comments";
                    param.DbType = DbType.String;
                    param.Value = comments;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UsedAsView";
                    param.DbType = DbType.Boolean;
                    param.Value = usedAsView;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = "SELECT @@IDENTITY";
                    string identity = GenericDataAccess.ExecuteScalar(command, false);

                    command.CommandText = @"INSERT INTO ReportDataLocations(RepID, DataDescription,DataPosition, 
                        DataType, ShortCode) VALUES 
                        (@RepID, 'Facility Code', 1, 'TEXT', 'FACCODE'),
                        (@RepID, 'Month of Report', 2, 'INTEGER', 'MONTH'),
                        (@RepID, 'Year of Report', 3, 'INTEGER', 'YEAR')";
                    command.Parameters.Clear();
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = identity;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"INSERT INTO ReportDataLocations(RepID,DataDescription,DataPosition,DataType,
                        ShortCode) VALUES (@RepID, 'Description', @DataPosition, 'INTEGER', 'SHORTCODE')";
                    for (int i = 3; i < dataCount; i++)
                    {
                        command.Parameters.Clear();
                        param = command.CreateParameter();
                        param.ParameterName = "@RepID";
                        param.DbType = DbType.Int32;
                        param.Value = identity;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@DataPosition";
                        param.DbType = DbType.Int32;
                        param.Value = (i + 1);
                        command.Parameters.Add(param);
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    status = true;
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.CreateReport(name, repVersion, dataCount, description, comments, 
                        usedAsView, userSignature);
                    output = DataTransformation.Decrypt(output);
                    status = bool.Parse(output);
                    break;
            }
            return status;
        }

        public static bool IsRepVersionUsable(string repVersion)
        {
            bool usable = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(RepVersion) AS [COUNT] FROM Report 
                        WHERE LOWER(RepVersion) = @RepVersion";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepVersion";
                    param.DbType = DbType.String;
                    param.Value = repVersion.ToLower();
                    command.Parameters.Add(param);
                    string sCount = GenericDataAccess.ExecuteScalar(command);
                    int count = Int32.Parse(sCount);
                    usable = (count == 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.IsRepVersionUsable(repVersion);
                    output = DataTransformation.Decrypt(output);
                    usable = bool.Parse(output);
                    break;
            }
            return usable;
        }

        public static void DeleteReport(int reportID)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM ReportDataLocations WHERE RepID=@RepID";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"DELETE FROM ReportBusinessRules WHERE RepID=@RepID";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"DELETE FROM Report WHERE RepID=@RepID";
                    GenericDataAccess.ExecuteNonQuery(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    webService.DeleteReport(reportID);
                    break;
            }
        }

        public static bool ReportCanBeDeleted(int reportID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ReportsCanBeDeleted.ContainsKey(reportID))
                    return cache_ReportsCanBeDeleted[reportID];
            }
            bool canBeDeleted = false;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(RepID) AS [count] FROM ReportData WHERE RepID = @RepID";

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    string data = GenericDataAccess.ExecuteScalar(command);
                    int count = Int32.Parse(data);
                    canBeDeleted = (count == 0);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(RepID) AS [count] FROM ReportData WHERE RepID = @RepID";

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    string data2 = GenericDataAccess.ExecuteScalar(command);
                    int count2 = Int32.Parse(data2);
                    canBeDeleted = (count2 == 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.ReportCanBeDeleted(reportID);
                    output = DataTransformation.Decrypt(output);
                    canBeDeleted = bool.Parse(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_ReportsCanBeDeleted[reportID] = canBeDeleted;
            return canBeDeleted;
        }

        public static DataTable GetReportDataLocations(int reportID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ReportDataLocations.ContainsKey(reportID))
                    return cache_ReportDataLocations[reportID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT MeasureNo,DataDescription,DataPosition,DataType,ShortCode
                        FROM ReportDataLocations WHERE RepID = @RepID";
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT MeasureNo,DataDescription,DataPosition,DataType,ShortCode
                        FROM ReportDataLocations WHERE RepID = @RepID";
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportDataLocations(reportID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_ReportDataLocations[reportID] = dataTable;
            return dataTable;
        }

        public static int GetReportDataLocationsCount(int reportID)
        {
            int count = 0;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(RepID) AS [count] FROM ReportDataLocations 
                        WHERE RepID = @RepID";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    string data = GenericDataAccess.ExecuteScalar(command);
                    count = Int32.Parse(data);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportDataLocationsCount(reportID);
                    output = DataTransformation.Decrypt(output);
                    count = Int32.Parse(output);
                    break;
            }
            return count;
        }

        public static bool UpdateReportKeyword(int reportID, string keyword)
        {
            bool updated = false;
            string output = String.Empty;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(RepVersion) AS [count] FROM Report 
                        WHERE RepVersion=@RepVersion AND RepID <> @RepID";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RepVersion";
                    param.DbType = DbType.String;
                    param.Value = keyword;
                    command.Parameters.Add(param);
                    output = GenericDataAccess.ExecuteScalar(command, false);
                    int count = Int32.Parse(output);
                    if (count == 0)
                    {
                        command.CommandText = "UPDATE Report SET RepVersion=@RepVersion WHERE RepID=@RepID";
                        count = GenericDataAccess.ExecuteNonQuery(command, true);
                        updated = (count == 1);
                    }
                    else
                    {
                        if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                        updated = false;
                    }
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    output = webService.UpdateReportKeyword(reportID, keyword);
                    output = DataTransformation.Decrypt(output);
                    updated = Boolean.Parse(output);
                    break;
            }
            return updated;
        }

        public static void SetReportDataLocations(int reportID, string[][] data)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(RepID) AS [count] FROM ReportDataLocations WHERE RepID=@RepID";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    string sCount = GenericDataAccess.ExecuteScalar(command, false);

                    int count = Int32.Parse(sCount);
                    if (count > data.Length)
                    {
                        command.CommandText = @"DELETE FROM ReportBusinessRules WHERE RepID=@RepID";
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    command.CommandText = @"DELETE FROM ReportDataLocations WHERE RepID=@RepID";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"INSERT INTO ReportDataLocations(RepID, DataDescription, 
                        DataPosition, DataType, ShortCode) VALUES(@RepID, @DataDescription, 
                        @DataPosition, @DataType, @ShortCode)";
                    for (int i = 0; i < data.Length; i++)
                    {
                        command.Parameters.Clear();
                        param = command.CreateParameter();
                        param.ParameterName = "@RepID";
                        param.DbType = DbType.Int32;
                        param.Value = reportID;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@DataDescription";
                        param.DbType = DbType.String;
                        param.Value = data[i][1];
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@DataPosition";
                        param.DbType = DbType.Int32;
                        param.Value = data[i][0];
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@DataType";
                        param.DbType = DbType.String;
                        param.Value = data[i][2];
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@ShortCode";
                        param.DbType = DbType.String;
                        param.Value = data[i][3];
                        command.Parameters.Add(param);
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    webService.SetReportDataLocations(reportID, data);
                    break;
            }
        }
        #endregion

        #region Report Rules Management
        public static DataTable GetReportRules(int reportID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_ReportRules.ContainsKey(reportID))
                    return cache_ReportRules[reportID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT rb.BRNo, rb.RepID, rb.MeasurePosNo, rb.RuleDescription, rb.Action, 
                        rb.ComparedToOrderPos, rb.ComparisonType, rb.Multicomparison, ct.ComparisonSign 
                        FROM ReportBusinessRules AS rb 
                        INNER JOIN ComparisonType AS ct ON rb.ComparisonType=ct.ComparisonType
                        WHERE RepID=@RepID ORDER BY MeasurePosNo";
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT rb.BRNo, rb.RepID, rb.MeasurePosNo, rb.RuleDescription, rb.Action, 
                        rb.ComparedToOrderPos, rb.ComparisonType, rb.Multicomparison, ct.ComparisonSign 
                        FROM ReportBusinessRules AS rb 
                        INNER JOIN ComparisonType AS ct ON rb.ComparisonType=ct.ComparisonType
                        WHERE RepID=@RepID ORDER BY MeasurePosNo";
                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportRules(reportID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_ReportRules[reportID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAllComparison()
        {
            if (AppConfiguration.DataCached)
            {
                if (AllComparisons != null) return AllComparisons;
            }

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ComparisonType, ComparisonSign FROM ComparisonType";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ComparisonType, ComparisonSign FROM ComparisonType";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllReportRulesComparison();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) AllComparisons = dataTable;
            return dataTable;
        }

        public static bool DeleteReportRule(int reportID, int ruleID)
        {
            bool deleted = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM ReportBusinessRules WHERE RepID=@RepID AND BRNo=@BRNo";
                    
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@BRNo";
                    param.DbType = DbType.Int32;
                    param.Value = ruleID;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);
                    deleted = (affected == 1);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.DeleteReportRule(reportID, ruleID);
                    output = DataTransformation.Decrypt(output);
                    deleted = bool.Parse(output);
                    break;
            }
            return deleted;
        }

        public static bool InsertReportRule(int reportID, int measurePosNo, string ruleDescription, 
            string comparedToOrderPos, int comparisonType, bool multicomparison)
        {
            bool inserted = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"INSERT INTO ReportBusinessRules(RepID, MeasurePosNo, RuleDescription, 
                        Action, ComparedToOrderPos, ComparisonType, Multicomparison) VALUES(@RepID, @MeasurePosNo, 
                        @RuleDescription, 1, @ComparedToOrderPos, @ComparisonType, @Multicomparison)";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@MeasurePosNo";
                    param.DbType = DbType.Int32;
                    param.Value = measurePosNo;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RuleDescription";
                    param.DbType = DbType.String;
                    param.Value = ruleDescription;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ComparedToOrderPos";
                    param.DbType = DbType.String;
                    param.Value = comparedToOrderPos;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ComparisonType";
                    param.DbType = DbType.Int32;
                    param.Value = comparisonType;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Multicomparison";
                    param.DbType = DbType.Boolean;
                    param.Value = multicomparison;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);
                    inserted = (affected == 1);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.InsertReportRule(reportID, measurePosNo, 
                        ruleDescription, comparedToOrderPos, comparisonType, multicomparison);
                    output = DataTransformation.Decrypt(output);
                    inserted = bool.Parse(output);
                    break;
            }
            return inserted;
        }

        public static bool UpdateReportRule(int reportID, int measurePosNo, string ruleDescription, 
            string comparedToOrderPos, int comparisonType, bool multicomparison, int BRNo)
        {
            bool updated = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"UPDATE ReportBusinessRules SET RepID=@RepID, MeasurePosNo=@MeasurePosNo, 
                        RuleDescription=@RuleDescription, ComparedToOrderPos=@ComparedToOrderPos, 
                        ComparisonType=@ComparisonType, Multicomparison=Multicomparison 
                        WHERE RepID=@RepID AND BRNo=@BRNo";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@MeasurePosNo";
                    param.DbType = DbType.Int32;
                    param.Value = measurePosNo;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RuleDescription";
                    param.DbType = DbType.String;
                    param.Value = ruleDescription;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ComparedToOrderPos";
                    param.DbType = DbType.String;
                    param.Value = comparedToOrderPos;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ComparisonType";
                    param.DbType = DbType.Int32;
                    param.Value = comparisonType;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Multicomparison";
                    param.DbType = DbType.Boolean;
                    param.Value = multicomparison;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@BRNo";
                    param.DbType = DbType.Int32;
                    param.Value = BRNo;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);
                    updated = (affected == 1);
                    break;
                        
                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.UpdateReportRule(reportID, measurePosNo, ruleDescription, 
                        comparedToOrderPos, comparisonType, multicomparison, BRNo);
                    output = DataTransformation.Decrypt(output);
                    updated = bool.Parse(output);
                    break;
            }
            return updated;
        }
        #endregion

        #endregion

        #region Help or Assistance Methods
        /// <summary>
        /// Gets help seeker details from his/her registered cell number
        /// </summary>
        /// <param name="cellnum">Cell number of help seeker</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetHelpSeekerDetailsFromCellnum(string cellnum)
        {
            string query = @"SELECT ApprovedSMSCells.CellNum AS HelpSeekerCellNum, ApprovedSMSCells.Name AS HelpSeekerName, 
                ApprovedSMSCells.FacCode AS HelpSeekerFacilityCode, Facilities.FacName AS HelpSeekerFacilityName, 
                District.District AS HelpSeekerFacilityDistrict, Facilities.Region AS HelpSeekerRegionID, 
                Facilities.District AS HelpSeekerDistrictID, ApprovedSMSCells.LangID AS HelpSeekerLanguageID 
                FROM ApprovedSMSCells INNER JOIN Facilities 
                ON ApprovedSMSCells.FacCode = Facilities.FacCode INNER JOIN District ON Facilities.District = District.DistrictNo
                WHERE (ApprovedSMSCells.FacCode IS NOT NULL) AND (ApprovedSMSCells.CellNum = @CellNum)";
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = query;
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@CellNum";
            param.DbType = DbType.String;
            param.Value = cellnum;
            command.Parameters.Add(param);
            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        /// <summary>
        /// Gets registered users who are assigned to provide help to facility identified by facilityCode at Facility Level
        /// </summary>
        /// <param name="facilityCode">Unique identifier of facility</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetFacilityHelp(string facilityCode)
        {
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, ApprovedSMSCells.Name, 
                ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, ApprovedSMSCells.Email
                FROM ApprovedSMSCells INNER JOIN Assistance ON ApprovedSMSCells.ApprovedCellNo = Assistance.ApprovedCellNo
                WHERE (Assistance.FacCode = @FacCode)";
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = query;
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@FacCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);
            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        /// <summary>
        /// Gets registered users who are assigned to provide help/assistance to district identified by districtID
        /// </summary>
        /// <param name="districtID">Unique identifier of district</param>
        /// <returns>DataTable object</returns>
        public static DataTable GetDistrictHelp(int districtID)
        {
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, ApprovedSMSCells.Name, 
                ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, ApprovedSMSCells.Email
                FROM ApprovedSMSCells INNER JOIN Assistance ON ApprovedSMSCells.ApprovedCellNo = Assistance.ApprovedCellNo
                WHERE (Assistance.DistrictID = @DistrictID)";
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = query;
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@DistrictID";
            param.DbType = DbType.Int32;
            param.Value = districtID;
            command.Parameters.Add(param);
            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        /// <summary>
        /// Gets registered users who are assigned to provide help/assistance in region identified by regionID
        /// </summary>
        /// <param name="regionID">Unique identifier of regionID</param>
        /// <returns></returns>
        public static DataTable GetRegionHelp(int regionID)
        {
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, ApprovedSMSCells.Name, 
                ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, ApprovedSMSCells.Email
                FROM ApprovedSMSCells INNER JOIN Assistance ON ApprovedSMSCells.ApprovedCellNo = Assistance.ApprovedCellNo
                WHERE (Assistance.RegionID = @RegionID)";
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = query;
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@RegionID";
            param.DbType = DbType.Int32;
            param.Value = regionID;
            command.Parameters.Add(param);
            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            return dataTable;
        }

        /// <summary>
        /// Sends assistance/help notification to assigned user based on the help seek registered cell number
        /// </summary>
        /// <param name="cellnum">Help seeker registered number</param>
        /// <returns>True if success otherwise false</returns>
        public static bool SendAssistance(string cellnum)
        {
            const int SEEKER_MESSAGE_LABEL_ID = 25;
            const int HELPER_MESSAGE_LABEL_ID = 26;
            const int UNKNOWN_HELP_SEEKER_MESSAGE_LABEL_ID = 70;
            const int DEFAULT_HELPER_LABEL_ID = 71;

            DataTable dataTable = GetHelpSeekerDetailsFromCellnum(cellnum);
            if (dataTable.Rows.Count < 1)
            {
                ShortMessage message = new ShortMessage();
                message.Sender = cellnum;
                message.Message = GetTranslationText(cellnum, SEEKER_MESSAGE_LABEL_ID);
                message.SendDBSMS();

                string helperNumber = GetTranslationText(cellnum, DEFAULT_HELPER_LABEL_ID);
                message.Sender = helperNumber;
                message.Message = GetTranslationText(helperNumber, UNKNOWN_HELP_SEEKER_MESSAGE_LABEL_ID);
                message.Message = String.Format(message.Message, cellnum);
                message.SendDBSMS();
                return true;
            }
            else
            {
                string helpSeekerCellNum = dataTable.Rows[0]["HelpSeekerCellNum"].ToString();
                string helpSeekerName = dataTable.Rows[0]["HelpSeekerName"].ToString();
                string helpSeekerFacilityCode = dataTable.Rows[0]["HelpSeekerFacilityCode"].ToString();
                string helpSeekerFacilityName = dataTable.Rows[0]["HelpSeekerFacilityName"].ToString();
                string helpSeekerFacilityDistrict = dataTable.Rows[0]["HelpSeekerFacilityDistrict"].ToString();
                int helpSeekerRegionID = int.Parse(dataTable.Rows[0]["HelpSeekerRegionID"].ToString());
                int helpSeekerDistrictID = int.Parse(dataTable.Rows[0]["HelpSeekerDistrictID"].ToString());
                int helpSeekerLanguageID = int.Parse(dataTable.Rows[0]["HelpSeekerLanguageID"].ToString());
                DataTable helperDataTable = null;

                DataTable facilityHelpDataTable = GetFacilityHelp(helpSeekerFacilityCode);
                if (facilityHelpDataTable.Rows.Count < 1)
                {
                    DataTable districtHelpDataTable = GetDistrictHelp(helpSeekerDistrictID);
                    if (districtHelpDataTable.Rows.Count < 1)
                    {
                        DataTable regionHelpDataTable = GetRegionHelp(helpSeekerRegionID);
                        if (regionHelpDataTable.Rows.Count < 1) return false;
                        else helperDataTable = regionHelpDataTable;
                    }
                    else helperDataTable = districtHelpDataTable;
                }
                else helperDataTable = facilityHelpDataTable;

                foreach (DataRow row in helperDataTable.Rows)
                {
                    string helperCellnum = row["CellNum"].ToString();
                    string helperEmail = row["Email"].ToString();

                    ShortMessage message = new ShortMessage();
                    string text = GetTranslationText(helperCellnum, HELPER_MESSAGE_LABEL_ID);
                    //string helperSMS = String.Format("{0} of {1} in {2} is requesting help on using IQSMS");
                    string helperSMS = String.Format(text, helpSeekerName, helpSeekerCellNum, helpSeekerFacilityName, helpSeekerFacilityDistrict);
                    message.Sender = helperCellnum;
                    message.Message = helperSMS;
                    message.SendDBSMS();
                    //SMSAccess.SendDBSMS(message);

                    message = new ShortMessage();
                    message.Sender = helpSeekerCellNum;
                    //string helpSeekerSMS = String.Format("Your request on how to use IQSMS has been sent to responsible personnel");
                    message.Message = GetTranslationText(helpSeekerCellNum, SEEKER_MESSAGE_LABEL_ID);
                    message.SendDBSMS();
                    //SMSAccess.SendDBSMS(message);

                    Utilities.SendMail(helperEmail, String.Format("{0} Help Request", AppConfiguration.ApplicationName), helperSMS);
                }
                return true;
            }
            
        }
        #endregion

        #region Translation Methods
        /// <summary>
        /// Gets text of label labelID based on the language set by the user with registered cell number cellnum
        /// </summary>
        /// <param name="cellnum">Registered user cell number</param>
        /// <param name="labelID">Unique identifier of label that requires language translation</param>
        /// <returns></returns>
        public static string GetTranslationText(string cellnum, int labelID)
        {
            string text = String.Empty;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    //DbCommand command = GenericDataAccess.CreateCommand();
                    //command.CommandType = CommandType.StoredProcedure;
                    //command.CommandText = "GetTransText";
                    
                    //DbParameter param = command.CreateParameter();
                    //param.ParameterName = "@SMSNumber";
                    //param.DbType = DbType.String;
                    //param.Value = cellnum;
                    //command.Parameters.Add(param);

                    //param = command.CreateParameter();
                    //param.ParameterName = "@LabelNo";
                    //param.DbType = DbType.Int32;
                    //param.Value = labelID;
                    //command.Parameters.Add(param);
                    //text = GenericDataAccess.ExecuteScalar(command);

                    int language = DataModels.Models.Language.DEFAULT_LANGUAGE_ID;
                    using (var db = new DataModels.Models.Context.IQSMS_TestDBContext())
                    {
                        var userInformation = (from u in db.ApprovedSMSCells
                                               where u.CellNum == cellnum
                                               select u).FirstOrDefault();
                        if (userInformation != null)
                        {
                            if (userInformation.LangID.HasValue) language = userInformation.LangID.Value;
                        }

                        text = (from t in db.Translations
                                where t.LabelNo == labelID && t.LangID == language
                                select t.LText).FirstOrDefault();
                    }
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetTranslationText(cellnum, labelID);
                    text = DataTransformation.Decrypt(output);
                    break;
            }            
            return text;
        }

        public static string GetTranslationText(int labelID)
        {
            string cellnum = "ANONYMOUS USER";
            string text = GetTranslationText(cellnum, labelID);
            //switch (AppConfiguration.AccessMethod)
            //{
            //    case DataAccessMethod.DIRECT_ACCESS:
            //        DbCommand command = GenericDataAccess.CreateCommand();
            //        command.CommandType = CommandType.StoredProcedure;
            //        command.CommandText = "GetTransText";

            //        DbParameter param = command.CreateParameter();
            //        param.ParameterName = "@SMSNumber";
            //        param.DbType = DbType.String;
            //        param.Value = cellnum;
            //        command.Parameters.Add(param);

            //        param = command.CreateParameter();
            //        param.ParameterName = "@LabelNo";
            //        param.DbType = DbType.Int32;
            //        param.Value = labelID;
            //        command.Parameters.Add(param);
            //        text = GenericDataAccess.ExecuteScalar(command);
            //        break;

            //    case DataAccessMethod.WEB_SERVICES:
            //        string output = webService.GetTranslationText(cellnum, labelID);
            //        text = DataTransformation.Decrypt(output);
            //        break;
            //}
            return text;
        }

        public static DataTable GetAllTranslationByLanguage(int languageID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllLanguageTranslations.ContainsKey(languageID))
                    return cache_AllLanguageTranslations[languageID];
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT TransID, LangID, LabelNo, LText FROM Translations WHERE LangID = @LangID";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = languageID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT TransID, LangID, LabelNo, LText FROM Translations WHERE LangID = @LangID";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = languageID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllTranslationByLanguage(languageID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AllLanguageTranslations[languageID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAllLanguages()
        {
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT LangID, Language FROM Languages";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT LangID, Language FROM Languages";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllLanguage();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetTranslationByLabelNo(int languageID, int labelNo)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_LanguageTranslationByLabelNo.ContainsKey(languageID))
                {
                    Dictionary<int, DataTable> data = cache_LanguageTranslationByLabelNo[languageID];
                    if (data != null)
                        if (data.ContainsKey(labelNo)) 
                            return data[labelNo];
                }
            }
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT TransID, LangID, LabelNo, LText FROM Translations 
                        WHERE LangID=@LangID AND LabelNo=@LabelNo";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
            
                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = languageID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LabelNo";
                    param.DbType = DbType.Int32;
                    param.Value = labelNo;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT TransID, LangID, LabelNo, LText FROM Translations 
                        WHERE LangID=@LangID AND LabelNo=@LabelNo";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
            
                    param = command.CreateParameter();
                    param.ParameterName = "@LangID";
                    param.DbType = DbType.Int32;
                    param.Value = languageID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LabelNo";
                    param.DbType = DbType.Int32;
                    param.Value = labelNo;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetTranslationByLabelNo(languageID, labelNo);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached)
            {
                if (cache_LanguageTranslationByLabelNo.ContainsKey(languageID))
                {
                    Dictionary<int, DataTable> data = cache_LanguageTranslationByLabelNo[languageID];
                    data[labelNo] = dataTable;
                }
                else
                {
                    Dictionary<int, DataTable> data = new Dictionary<int,DataTable>();
                    data[labelNo] = dataTable;
                    cache_LanguageTranslationByLabelNo[languageID] = data;
                }
            }
            return dataTable;
        }

        public static bool UpdateTranslation(int transID, string languageText)
        {
            bool status = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"UPDATE Translations SET LText = @LText WHERE TransID = @TransID";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@LText";
                    param.DbType = DbType.String;
                    param.Value = languageText;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@TransID";
                    param.DbType = DbType.Int32;
                    param.Value = transID;
                    command.Parameters.Add(param);
                    int affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    status = (affectedRows > 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.UpdateTranslation(transID, languageText);
                    output = DataTransformation.Decrypt(output);
                    status = bool.Parse(output);
                    break;
            }
            return status;
        }

        #endregion

        #region Other Methods
        /// <summary>
        /// Returns text representing the month specified by period
        /// </summary>
        /// <param name="period">Period or month</param>
        /// <param name="shortForm">False for long form otherwise 3 digit text</param>
        /// <returns>String containing month text</returns>
        public static string GetMonthText(int period, bool shortForm = false)
        {
            string text = String.Empty;
            switch (period)
            {
                case 1:
                    text = "January";
                    break;

                case 2:
                    text = "February";
                    break;

                case 3:
                    text = "March";
                    break;

                case 4:
                    text = "April";
                    break;

                case 5:
                    text = "May";
                    break;

                case 6:
                    text = "June";
                    break;

                case 7:
                    text = "July";
                    break;

                case 8:
                    text = "August";
                    break;

                case 9:
                    text = "September";
                    break;

                case 10:
                    text = "October";
                    break;

                case 11:
                    text = "November";
                    break;

                case 12:
                    text = "December";
                    break;
            }
            if (shortForm) text = text.Substring(0, 3);
            return text;
        }

        public static bool Compare(decimal value1, string sign, decimal value2)
        {
            bool result = false;
            sign = sign.ToLower();
            switch (sign)
            {
                case "<":
                case "less than":
                    result = value1 < value2;
                    break;

                case "<=":
                case "less than or equals":
                    result = value1 <= value2;
                    break;

                case "=":
                case "equals":
                    result = value1 == value2;
                    break;

                case ">=":
                case "greater than or equals":
                    result = value1 >= value2;
                    break;

                case ">":
                case "greater than":
                    result = value1 > value2;
                    break;

                case "!=":
                case "not equals":
                    result = value1 != value2;
                    break;

                default:
                    result = false;
                    break;
            }
            return result;
        }

        public static string GetSetting(string name)
        {
            string setting = String.Empty;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT SettingValue FROM SysSettings WHERE SettingName=@SettingName";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@SettingName";
                    param.DbType = DbType.String;
                    param.Size = 50;
                    param.Value = name;
                    command.Parameters.Add(param);
                    setting = GenericDataAccess.ExecuteScalar(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    throw new NotImplementedException("This feature does not support MS Access back-end");

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSetting(name);
                    setting = DataTransformation.Decrypt(output);
                    break;
            }
            return setting;
        }

        /// <summary>
        /// Getting the setting from the database.
        /// If the value is not set, the defaultValueIfMissing will be set and returned.
        /// </summary>
        /// <param name="name">Setting name</param>
        /// <param name="defaultValueIfMissing">Default value of the setting if not set</param>
        /// <returns></returns>
        public static string GetSetting(string name, string defaultValueIfMissing)
        {
            string setting = GetSetting(name);
            if (string.IsNullOrWhiteSpace(setting))
            {
                SetSetting(name, defaultValueIfMissing);
                setting = defaultValueIfMissing;
            }
            
            return setting;
        }

        public static void SetSetting(string name, object value)
        {
            if (value != null)
            {
                string sValue = value.ToString();
                SetSetting(name, sValue);
            }
        }

        public static void SetSetting(string name, string value)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM SysSettings WHERE SettingName=@SettingName";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@SettingName";
                    param.DbType = DbType.String;
                    param.Value = name;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"INSERT INTO SysSettings(SettingName,SettingValue) 
                        VALUES(@SettingName,@SettingValue)";        
                    param = command.CreateParameter();
                    param.ParameterName = "@SettingValue";
                    param.DbType = DbType.String;
                    param.Value = value;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    webService.SetSetting(name, value);
                    break;
            }
        }

        public static DataTable GetMessageHistory(string phoneNumber)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT [Date],[SMSType] AS [Received],[Message] FROM SMSLog WHERE CellNum=@CellNum";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command); 
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT [Date],[SMSType] AS [Received],[Message] FROM SMSLog WHERE CellNum=@CellNum";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command); 
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetMessageHistory(phoneNumber);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static int GetErrorMessageCount(string phoneNumber)
        {
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            int count = 0;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT COUNT(SenderNum) FROM ErrMsgSMS WHERE SenderNum=@CellNum";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);
                    string sCount = GenericDataAccess.ExecuteScalar(command);
                    count = Int32.Parse(sCount);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT COUNT(SenderNum) FROM ErrMsgSMS WHERE SenderNum=@CellNum";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@CellNum";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);
                    string c = GenericDataAccess.ExecuteScalar(command);
                    count = Int32.Parse(c);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetErrorMessageCount(phoneNumber);
                    output = DataTransformation.Decrypt(output);
                    count = Int32.Parse(output);
                    break;
            }
            return count;
        }

        //public static DataTable RunCommandOnRemoteServer(IDbCommand command)
        //{
        //    if (!IsOperationAllowed(command.CommandText)) throw new Exception("Such operation is not allowed to run on server!");

        //    int commandType = -1;
        //    if (command.CommandType == CommandType.Text) commandType = Querying.SQLCOMMAND_TEXT;
        //    if (command.CommandType == CommandType.StoredProcedure) commandType = Querying.SQLCOMMAND_STORED_PROCEDURE;
        //    if (command.CommandType == CommandType.TableDirect) commandType = Querying.SQLCOMMAND_TABLE_DIRECT;

        //    List<string> parameterNames = new List<string>();
        //    List<int> parameterDbTypes = new List<int>();
        //    List<object> parameterValues = new List<object>();
        //    #region Filling Parameters
        //    foreach (DbParameter p in command.Parameters)
        //    {
        //        parameterNames.Add(p.ParameterName);
        //        switch (p.DbType)
        //        {
        //            case DbType.AnsiString:
        //            case DbType.AnsiStringFixedLength:
        //            case DbType.String:
        //            case DbType.StringFixedLength:
        //                parameterDbTypes.Add(Querying.DBTYPE_STRING);
        //                parameterValues.Add(p.Value);
        //                break;

        //            case DbType.Boolean:
        //                parameterDbTypes.Add(Querying.DBTYPE_BOOLEAN);
        //                parameterValues.Add(p.Value);
        //                break;

        //            case DbType.Date:
        //            case DbType.DateTime:
        //            case DbType.DateTime2:
        //            case DbType.DateTimeOffset:
        //            case DbType.Time:
        //                parameterDbTypes.Add(Querying.DBTYPE_DATETIME);
        //                try
        //                {
        //                    DateTime d = DateTime.Parse(p.Value.ToString());
        //                    string osi_format = String.Format("{0}-{1}-{2}", d.Year, d.Month, d.Day);
        //                    parameterValues.Add(osi_format);
        //                }
        //                catch
        //                {
        //                    parameterValues.Add(p.Value);
        //                }
        //                break;

        //            case DbType.Currency:
        //            case DbType.Decimal:
        //            case DbType.Double:
        //            case DbType.Single:
        //                parameterDbTypes.Add(Querying.DBTYPE_DECIMAL);
        //                parameterValues.Add(p.Value);
        //                break;

        //            case DbType.Int16:
        //            case DbType.Int32:
        //            case DbType.Int64:
        //            case DbType.UInt16:
        //            case DbType.UInt32:
        //            case DbType.UInt64:
        //            case DbType.SByte:
        //            case DbType.Byte:
        //                parameterDbTypes.Add(Querying.DBTYPE_INTEGER);
        //                parameterValues.Add(p.Value);
        //                break;

        //            case DbType.Guid:
        //            case DbType.Object:
        //            case DbType.VarNumeric:
        //            case DbType.Xml:
        //            case DbType.Binary:
        //            default:
        //                parameterDbTypes.Add(Querying.DBTYPE_STRING);
        //                parameterValues.Add(p.Value);
        //                break;
        //        }
        //    }
        //    #endregion

        //    string[] names = null;
        //    int[] dbTypes = null;
        //    object[] values = null;
        //    if (parameterNames.Count > 0)
        //    {
        //        names = parameterNames.ToArray();
        //        dbTypes = parameterDbTypes.ToArray();
        //        values = parameterValues.ToArray();
        //    }

        //    string output = webService.RunCommand(commandType, command.CommandText, names, values, dbTypes);
        //    DataTable dataTable = DataTransformation.Deserialize(output);
        //    return dataTable;
        //}

        //private static bool IsOperationAllowed(string commandText)
        //{
        //    if (commandText.Contains("CREATE DATABASE")) return false;
        //    if (commandText.Contains("CREATE TABLE")) return false;
        //    if (commandText.Contains("CREATE VIEW")) return false;
        //    if (commandText.Contains("CREATE PROCEDURE")) return false;
        //    if (commandText.Contains("CREATE FUNCTION")) return false;
        //    if (commandText.Contains("CREATE TRIGGER")) return false;
        //    if (commandText.Contains("CREATE SYNONYM")) return false;
            
        //    if (commandText.Contains("DROP DATABASE")) return false;
        //    if (commandText.Contains("DROP TABLE")) return false;
        //    if (commandText.Contains("DROP VIEW")) return false;
        //    if (commandText.Contains("DROP PROCEDURE")) return false;
        //    if (commandText.Contains("DROP FUNCTION")) return false;
        //    if (commandText.Contains("DROP TRIGGER")) return false;
        //    if (commandText.Contains("DROP SYNONYM")) return false;
        //    ;
        //    if (commandText.Contains("ALTER DATABASE")) return false;
        //    if (commandText.Contains("ALTER TABLE")) return false;
        //    if (commandText.Contains("ALTER VIEW")) return false;
        //    if (commandText.Contains("ALTER PROCEDURE")) return false;
        //    if (commandText.Contains("ALTER FUNCTION")) return false;
        //    if (commandText.Contains("ALTER TRIGGER")) return false;
        //    if (commandText.Contains("ALTER SYNONYM")) return false;

        //    ;
        //    if (commandText.Contains("INSERT INTO")) return false;
        //    if (commandText.Contains("DELETE FROM")) return false;
        //    if (commandText.Contains("TRUNCATE TABLE")) return false;
        //    if (commandText.Contains("UPDATE TABLE")) return false;
            
        //    if (commandText.Contains("RESTORE DATABASE")) return false;
        //    if (commandText.Contains("BACKUP DATABASE")) return false;
        //    return true;
        //}

        public static DataTable GetSupportingPartner()
        {
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Id, [Name], Description FROM SupportingPartners ORDER BY [Name] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Id, [Name], Description FROM SupportingPartners ORDER BY [Name] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSupportingPartner();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }
        #endregion

        #region User Management
        /// <summary>
        /// Gets DataTable object containing user information
        /// </summary>
        /// <param name="username">Username</param>
        /// <returns></returns>
        public static DataTable GetUserInformation(string username)
        {
            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"SELECT ID, Username, FirstName, LastName, Password, EmailAddress, 
                        PhoneNumber, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users WHERE Username = @Username";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@Username";
                    param.DbType = DbType.String;
                    param.Value = username;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetUserInformationByUsername(username);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            return dataTable;
        }

        /// <summary>
        /// Gets DataTable object containing user information
        /// </summary>
        /// <param name="username">Username</param>
        /// <param name="password">Password</param>
        /// <returns></returns>
        public static DataTable GetUserInformation(string username, string password)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, EmailAddress, PhoneNumber,
                        AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE Username=@Username AND Password=@Password";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@Username";
                    param.DbType = DbType.String;
                    param.Value = username;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Password";
                    param.DbType = DbType.String;
                    param.Value = DataTransformation.Encrypt(password);
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, EmailAddress, PhoneNumber,
                        AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE Username=@Username AND Password=@Password";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@Username";
                    param.DbType = DbType.String;
                    param.Value = username;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Password";
                    param.DbType = DbType.String;
                    param.Value = DataTransformation.Encrypt(password);
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetUserInformationByUsernamePassword(username, password);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }                      
            return dataTable;
        }

        /// <summary>
        /// Gets DataTable object containing user information
        /// </summary>
        /// <param name="userID">DB userID</param>
        /// <returns></returns>
        public static DataTable GetUserInformation(int userID)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, EmailAddress, 
                        PhoneNumber, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users WHERE ID = @UserID";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@UserID";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetUserInformationByID(userID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                     query = @"SELECT ID, Username, FirstName, LastName, Password, EmailAddress, 
                        AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users WHERE ID = @UserID";
                     command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@UserID";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;
            }

            return dataTable;
        }

        public static bool ChangePassword(int userID, string oldPassword, string newPassword)
        {
            bool status = false;
            switch (AppConfiguration.AccessMethod)
             {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"UPDATE Users SET Password=@NewPassword WHERE ID=@ID AND Password=@OldPassword";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@NewPassword";
                    param.DbType = DbType.String;
                    param.Value = DataTransformation.Encrypt(newPassword);
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@OldPassword";
                    param.DbType = DbType.String;
                    param.Value = DataTransformation.Encrypt(oldPassword);
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ID";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);
                    status = (affected > 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.ChangePassword(userID, oldPassword, newPassword);
                    output = DataTransformation.Decrypt(output);
                    status = bool.Parse(output);
                    break;
            }
            return status;
        }

        public static DataTable GetAllUsers()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllUsers != null) return cache_AllUsers;
            }

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId 
                        FROM Users ORDER BY FirstName ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId 
                        FROM Users ORDER BY FirstName ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllUsers();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetUsersByFacility(string facilityCode)
        {
            int accessLevel = ACCESS_LEVELS_FACILITY_ID;
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE AccessLevelValue=@FacilityCode AND AccessLevelID=@AccessLevelID ORDER BY FirstName ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandText = query;
                    command.CommandType = CommandType.Text;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevel;
                    command.Parameters.Add(param);

                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    //dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE AccessLevelValue=@FacilityCode AND AccessLevelID=@AccessLevelID ORDER BY FirstName ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    command.CommandType = CommandType.Text;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevel;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetUsersByFacility(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetUsersByDistrict(int districtId)
        {
            int accessLevel = ACCESS_LEVELS_DISTRICT_ID;

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE AccessLevelValue=@District AND AccessLevelID=@AccessLevelID ORDER BY FirstName ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandText = query;
                    command.CommandType = CommandType.Text;
                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.String;
                    param.Value = districtId;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevel;
                    command.Parameters.Add(param);

                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    //dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE AccessLevelValue=@District AND AccessLevelID=@AccessLevelID ORDER BY FirstName ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;                    
                    command.CommandType = CommandType.Text;
                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.String;
                    param.Value = districtId;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevel;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES: 
                    string output = webService.GetUsersByDistrict(districtId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetUsersByRegion(int regionId)
        {
            int accessLevel = ACCESS_LEVELS_REGION_ID;
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE AccessLevelValue=@RegionId AND AccessLevelID=@AccessLevelID ORDER BY FirstName ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandText = query;
                    command.CommandType = CommandType.Text;
                    param = command.CreateParameter();
                    param.ParameterName = "@RegionId";
                    param.DbType = DbType.String;
                    param.Value = regionId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevel;
                    command.Parameters.Add(param);

                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    //dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ID, Username, FirstName, LastName, Password, PhoneNumber,
                        EmailAddress, AccessLevelID, AccessLevelValue, SupportingPartnerId FROM Users 
                        WHERE AccessLevelValue=@RegionId AND AccessLevelID=@AccessLevelID ORDER BY FirstName ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    command.CommandType = CommandType.Text;
                    param = command.CreateParameter();
                    param.ParameterName = "@RegionId";
                    param.DbType = DbType.String;
                    param.Value = regionId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevel;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetUsersByRegion(regionId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetAllSMSUsers()
        {
            DataTable dataTable = null;
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, 
                ApprovedSMSCells.Name, ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, 
                ApprovedSMSCells.Email, Facilities.FacName, District.District, Region.RegionName 
                FROM District INNER JOIN Facilities ON District.DistrictNo = Facilities.District INNER JOIN
                Region ON Facilities.Region = Region.RegionNo RIGHT OUTER JOIN ApprovedSMSCells ON 
                Facilities.FacCode = ApprovedSMSCells.FacCode WHERE (ApprovedSMSCells.Deleted <> 1) OR
                (ApprovedSMSCells.Deleted IS NULL)";
            DbCommand command = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllSMSUsers();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            return dataTable;
        }

        public static DataTable GetAllSMSUsersByRegion(int regionId)
        {
            DataTable dataTable = null;
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, 
                ApprovedSMSCells.Name, ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, 
                ApprovedSMSCells.Email, Facilities.FacName, District.District, Region.RegionName 
                FROM District INNER JOIN Facilities ON District.DistrictNo = Facilities.District INNER JOIN
                Region ON Facilities.Region = Region.RegionNo RIGHT OUTER JOIN ApprovedSMSCells ON 
                Facilities.FacCode = ApprovedSMSCells.FacCode WHERE ((ApprovedSMSCells.Deleted <> 1) OR
                (ApprovedSMSCells.Deleted IS NULL)) AND (Region.RegionNo = @RegionNo) ";
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@RegionNo";
                    param.DbType = DbType.Int32;
                    param.Value = regionId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@RegionNo";
                    param.DbType = DbType.Int32;
                    param.Value = regionId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllSMSUsersByRegion(regionId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            return dataTable;
        }

        public static DataTable GetAllSMSUsersByDistrict(int districtId)
        {
            DataTable dataTable = null;
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, 
                ApprovedSMSCells.Name, ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, 
                ApprovedSMSCells.Email, Facilities.FacName, District.District, Region.RegionName 
                FROM District INNER JOIN Facilities ON District.DistrictNo = Facilities.District INNER JOIN
                Region ON Facilities.Region = Region.RegionNo RIGHT OUTER JOIN ApprovedSMSCells ON 
                Facilities.FacCode = ApprovedSMSCells.FacCode WHERE ((ApprovedSMSCells.Deleted <> 1) OR
                (ApprovedSMSCells.Deleted IS NULL)) AND (District.DistrictNo = @DistrictNo) ";
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictNo";
                    param.DbType = DbType.Int32;
                    param.Value = districtId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictNo";
                    param.DbType = DbType.Int32;
                    param.Value = districtId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllSMSUsersByDistrict(districtId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetAllSMSUsersByFacility(string facilityCode)
        {
            DataTable dataTable = null;
            string query = @"SELECT ApprovedSMSCells.ApprovedCellNo, ApprovedSMSCells.CellNum, 
                ApprovedSMSCells.Name, ApprovedSMSCells.LangID, ApprovedSMSCells.SendSMS, ApprovedSMSCells.FacCode, 
                ApprovedSMSCells.Email, Facilities.FacName, District.District, Region.RegionName 
                FROM District INNER JOIN Facilities ON District.DistrictNo = Facilities.District INNER JOIN
                Region ON Facilities.Region = Region.RegionNo RIGHT OUTER JOIN ApprovedSMSCells ON 
                Facilities.FacCode = ApprovedSMSCells.FacCode WHERE ((ApprovedSMSCells.Deleted <> 1) OR
                (ApprovedSMSCells.Deleted IS NULL)) AND (Facilities.FacCode = @FacCode) ";
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllSMSUsersByFacility(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static int CreateNewUser(string firstname, string lastname, string username, 
            string password, string email, string phoneNumber, int accessLevelID, string accessLevelValue,
            int supportingPartnerId, int actionUserId)
        {
            int insertID = -1;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"INSERT INTO Users(Username, FirstName, LastName, Password, EmailAddress, 
                        PhoneNumber, AccessLevelID, AccessLevelValue, SupportingPartnerId, CreateDate, CreatedByUser,
                        Deleted) 
                        VALUES (@Username, @FirstName, @LastName, @Password, @EmailAddress, @PhoneNumber, 
                        @AccessLevelID, @AccessLevelValue, @SupportingPartner, @CreateDate, @CreatedByUser,
                        @Deleted)";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@Username";
                    param.DbType = DbType.String;
                    param.Value = username;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FirstName";
                    param.DbType = DbType.String;
                    param.Value = firstname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LastName";
                    param.DbType = DbType.String;
                    param.Value = lastname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Password";
                    param.DbType = DbType.String;
                    param.Value = DataTransformation.Encrypt(password);
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@EmailAddress";
                    param.DbType = DbType.String;
                    param.Value = email;
                    command.Parameters.Add(param);                    

                    param = command.CreateParameter();
                    param.ParameterName = "@PhoneNumber";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = accessLevelID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelValue";
                    param.DbType = DbType.String;
                    param.Value = accessLevelValue;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartner";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@CreatedByUser";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);                    
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@CreateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);                    
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@Deleted";
                    param.DbType = DbType.Boolean;
                    param.Value = false;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command, false);
                    
                    if (affected == 1)
                    {
                        command.CommandText = "SELECT @@IDENTITY";
                        string output = GenericDataAccess.ExecuteScalar(command, false);
                        insertID = Int32.Parse(output);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string data = webService.CreateNewUser2(firstname, lastname, username, password, 
                        email, phoneNumber, accessLevelID, accessLevelValue, supportingPartnerId, userSignature);
                    data = DataTransformation.Decrypt(data);
                    insertID = Int32.Parse(data);
                    break;
            }
            return insertID;
        }

        public static bool UpdateUserDetails(int id, string firstname, string lastname,
            string password, string email, string phoneNumber, AccessLevel level, 
            string levelValue, int supportinPartnerId, int actionUserId)
        {
            bool success = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"UPDATE Users SET FirstName=@FirstName, LastName=@LastName, 
                        Password=@Password, EmailAddress=@EmailAddress, PhoneNumber=@PhoneNumber, 
                        AccessLevelID=@AccessLevelID, SupportingPartnerId=@SupportingPartnerId,
                        AccessLevelValue=@AccessLevelValue, UpdateDate=GETDATE(), 
                        UpdatedByUser=@UpdatedByUser WHERE ID=@ID";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FirstName";
                    param.DbType = DbType.String;
                    param.Value = firstname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LastName";
                    param.DbType = DbType.String;
                    param.Value = lastname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Password";
                    param.DbType = DbType.String;
                    param.Value = DataTransformation.Encrypt(password);
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@EmailAddress";
                    param.DbType = DbType.String;
                    param.Value = email;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PhoneNumber";
                    param.DbType = DbType.String;
                    param.Value = phoneNumber;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelID";
                    param.DbType = DbType.Int32;
                    param.Value = level;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@AccessLevelValue";
                    param.DbType = DbType.String;
                    param.Value = levelValue;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ID";
                    param.DbType = DbType.Int32;
                    param.Value = id;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportinPartnerId;
                    command.Parameters.Add(param);                    

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdatedByUser";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);
                    success = (affected == 1);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    IQServices.AccessLevel iLevel = IQServices.AccessLevel.RESTRICTED;
                    if (level == AccessLevel.ADMINISTRATOR) iLevel = IQServices.AccessLevel.ADMINISTRATOR;
                    if (level == AccessLevel.NATION) iLevel = IQServices.AccessLevel.NATION;
                    if (level == AccessLevel.REGION) iLevel = IQServices.AccessLevel.REGION;
                    if (level == AccessLevel.DISTRICT) iLevel = IQServices.AccessLevel.DISTRICT;
                    if (level == AccessLevel.FACILITY) iLevel = IQServices.AccessLevel.FACILITY;

                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.UpdateUserDetails2(id, firstname, lastname, password, email, 
                        phoneNumber, iLevel, levelValue, supportinPartnerId, userSignature);
                    output = DataTransformation.Decrypt(output);
                    success = bool.Parse(output);
                    break;
            }
            return success;
        }

        public static bool IsUsernameAvailable(string username)
        {
            bool available = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT COUNT(ID) AS [count] FROM Users WHERE Username=@Username";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@Username";
                    param.DbType = DbType.String;
                    param.Value = username;
                    command.Parameters.Add(param);
                    string sCount = GenericDataAccess.ExecuteScalar(command);

                    int iCount = Int32.Parse(sCount);
                    available = (iCount == 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.IsUsernameAvailable(username);
                    output = DataTransformation.Decrypt(output);
                    available = bool.Parse(output);
                    break;
            }
            return available;
        }

        /*public static bool DeleteSMSUser(int userId, int actionUserId)
        {
            bool success = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"UPDATE ApprovedSMSCells SET Deleted = 0, DeletedBy=@ActionUserId,
                        DeleteDate=@DeleteDate
                        WHERE ApprovedCellNo=@UserId";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@ID";
                    param.DbType = DbType.Int32;
                    param.Value = id;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);

                    success = (affected == 1);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.DeleteUser(id);
                    output = DataTransformation.Decrypt(output);
                    success = bool.Parse(output);
                    break;
            }
            return success;
        }*/

        public static bool DeleteUser(int id)
        {
            bool success = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM Users WHERE ID=@ID";
                    
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@ID";
                    param.DbType = DbType.Int32;
                    param.Value = id;
                    command.Parameters.Add(param);
                    int affected = GenericDataAccess.ExecuteNonQuery(command);
                    
                    success = (affected == 1);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.DeleteUser(id);
                    output = DataTransformation.Decrypt(output);
                    success = bool.Parse(output);
                    break;
            }
            return success;
        }

        public static bool AuthenticateUser(string userIdHash)
        {
            try
            {
                bool authenticated = false;
                string id = DataTransformation.Decrypt(userIdHash);
                switch (AppConfiguration.AccessMethod)
                {
                    case DataAccessMethod.DIRECT_ACCESS:
                        DbCommand command = GenericDataAccess.CreateCommand();
                        command.CommandType = CommandType.Text;
                        command.CommandText = @"SELECT COUNT(Users.ID) AS Expr1 FROM AccessLevels INNER JOIN
                            Users ON AccessLevels.AccessID = Users.AccessLevelID WHERE Users.ID=@ID AND Users.Deleted=0";

                        DbParameter param = command.CreateParameter();
                        param.ParameterName = "@ID";
                        param.DbType = DbType.Int32;
                        param.Value = id;
                        command.Parameters.Add(param);
                        string output = GenericDataAccess.ExecuteScalar(command);
                        int affected = Int32.Parse(output);
                        if (affected == 1) authenticated = true;
                        else authenticated = false;
                        break;

                    default:
                        authenticated = false;
                        break;
                }
                return authenticated;
            }
            catch
            {
                return false;
            }
        }

        public static bool AuthenticateUser(string userIdHash, out int accessLevel)
        {
            accessLevel = -1;
            try
            {
                bool authenticated = false;
                string id = DataTransformation.Decrypt(userIdHash);
                switch (AppConfiguration.AccessMethod)
                {
                    case DataAccessMethod.DIRECT_ACCESS:
                        DbCommand command = GenericDataAccess.CreateCommand();
                        command.CommandType = CommandType.Text;
                        command.CommandText = @"SELECT COUNT(Users.ID) AS Expr1, AccessLevels.AccessID
                            FROM AccessLevels INNER JOIN Users ON AccessLevels.AccessID = Users.AccessLevelID 
                            WHERE (Users.ID=@ID) AND (Users.Deleted=0) GROUP BY AccessLevels.AccessID";

                        DbParameter param = command.CreateParameter();
                        param.ParameterName = "@ID";
                        param.DbType = DbType.Int32;
                        param.Value = id;
                        command.Parameters.Add(param);
                        DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                        if (dataTable.Rows.Count == 1)
                        {
                            authenticated = true;
                            DataRow row = dataTable.Rows[0];
                            accessLevel = Int32.Parse(row["AccessID"].ToString());
                        }
                        else authenticated = false;
                        //string output = GenericDataAccess.ExecuteScalar(command);
                        //int affected = Int32.Parse(output);
                        //if (affected == 1) authenticated = true;
                        //else authenticated = false;
                        break;

                    default:
                        authenticated = false;
                        break;
                }
                return authenticated;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region FacilityDetails Class Methods
        [Obsolete("This method require too many details which are not used. Use another FacilityDetailsInsert2", true)]
        public static bool FacilityDetailsInsert(string code, string name, string shortname, int region, int district, 
            string description, string address, string principalContact, int status, string remarks,
            DateTime PMTCTStartDateTime, DateTime LDStartDateTime, DateTime prophylaxisDateTime,
            DateTime ANCStartDateTime, DateTime HEIDStartDate, bool provideANC, bool provideHEID, bool providePMTCT, 
            bool provideLD, bool provideProphylaxis,  DateTime activeDateTime, DateTime inactiveDateTime, bool trained)
        {
            bool okToContinue = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"INSERT INTO Facilities(FacCode, FacName, FacShortName, Region, District, PMTCT, LD,
                        Description, Address, PrincipalContact, Status, Remarks, PMTCTStartDate, LDStartDate, ANCStartDate,
                        HEIDStartDate, ANC, HEID, Prophylaxis, ProphylaxisStartDate, ActiveDate, InactiveDate, Trained)
                        VALUES(@FacCode, @FacName, @FacShortName, @Region, @District, @PMTCT, @LD,
                        @Description, @Address, @PrincipalContact, @Status, @Remarks, @PMTCTStartDate, @LDStartDate, @ANCStartDate,
                        @HEIDStartDate, @ANC, @HEID, @Prophylaxis, @ProphylaxisStartDate, @ActiveDate, @InactiveDate, @Trained)";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    #region Setting Command Parameters
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = code;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacName";
                    param.DbType = DbType.String;
                    param.Value = name;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacShortName";
                    param.DbType = DbType.String;
                    param.Value = shortname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = region;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.Int32;
                    param.Value = district;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PMTCT";
                    param.DbType = DbType.Boolean;
                    param.Value = providePMTCT;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LD";
                    param.DbType = DbType.Boolean;
                    param.Value = provideLD;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Description";
                    param.DbType = DbType.String;
                    param.Value = description;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Address";
                    param.DbType = DbType.String;
                    param.Value = address;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PrincipalContact";
                    param.DbType = DbType.String;
                    param.Value = principalContact;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Status";
                    param.DbType = DbType.Int32;
                    param.Value = status;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Remarks";
                    param.DbType = DbType.String;
                    param.Value = remarks;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PMTCTStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = PMTCTStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = LDStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANCStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = ANCStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEIDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = HEIDStartDate;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANC";
                    param.DbType = DbType.Boolean;
                    param.Value = provideANC;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEID";
                    param.DbType = DbType.Boolean;
                    param.Value = provideHEID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Prophylaxis";
                    param.DbType = DbType.Boolean;
                    param.Value = provideProphylaxis;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ProphylaxisStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = prophylaxisDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ActiveDate";
                    param.DbType = DbType.DateTime;
                    param.Value = activeDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@InactiveDate";
                    param.DbType = DbType.DateTime;
                    param.Value = inactiveDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Trained";
                    param.DbType = DbType.Boolean;
                    param.Value = trained;
                    command.Parameters.Add(param);
                    #endregion

                    int affectedRows = -1;
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    okToContinue = (affectedRows > 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.FacilityDetailsInsert(code, name, shortname, region, district, description,
                        address, principalContact, status, remarks, PMTCTStartDateTime, LDStartDateTime, prophylaxisDateTime,
                        ANCStartDateTime, HEIDStartDate, provideANC, provideHEID, providePMTCT, provideLD, provideProphylaxis,
                        activeDateTime, inactiveDateTime, trained);
                    output = DataTransformation.Decrypt(output);
                    okToContinue = bool.Parse(output);
                    break;
            }
            return okToContinue;
        }

        public static bool FacilityDetailsInsert2(string code, string name, string internalName, string shortname, int region, int district,
            string description, string address, string principalContact, string remarks,
            DateTime LDStartDateTime, DateTime prophylaxisDateTime,
            DateTime ANCStartDateTime, DateTime HEIDStartDate, bool provideANC, bool provideHEID,
            bool provideLD, bool provideProphylaxis, DateTime activityDateTime, bool actived, bool trained,
            bool provideDBS, int facilityType, int supportingPartnerId, int actionUserId, int status)
        {
            bool okToContinue = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"INSERT INTO Facilities(FacCode, FacName, FacShortName, Region, District, LD,
                        Description, Address, PrincipalContact, Remarks, LDStartDate, ANCStartDate, HEIDStartDate, 
                        ANC, HEID, Prophylaxis, ProphylaxisStartDate, ActiveDate, Activated, Trained, ProvideDBS, 
                        InternalName, CreatedByUser, FacilityType, SupportingPartnerId, Status, CreateDate)
                        VALUES(@FacCode, @FacName, @FacShortName, @Region, @District, @LD,
                        @Description, @Address, @PrincipalContact, @Remarks, @LDStartDate, @ANCStartDate,
                        @HEIDStartDate, @ANC, @HEID, @Prophylaxis, @ProphylaxisStartDate, @ActivityDate, @Activated, 
                        @Trained, @ProvideDBS, @InternalName, @CreatedByUser, @FacilityType, @SupportingPartnerId,
                        @Status, @CreateDate)";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    #region Setting Command Parameters
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = code;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacName";
                    param.DbType = DbType.String;
                    param.Value = name;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@InternalName";
                    param.DbType = DbType.String;
                    param.Value = internalName;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacShortName";
                    param.DbType = DbType.String;
                    param.Value = shortname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = region;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.Int32;
                    param.Value = district;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LD";
                    param.DbType = DbType.Boolean;
                    param.Value = provideLD;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Description";
                    param.DbType = DbType.String;
                    param.Value = description;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Address";
                    param.DbType = DbType.String;
                    param.Value = address;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PrincipalContact";
                    param.DbType = DbType.String;
                    param.Value = principalContact;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Remarks";
                    param.DbType = DbType.String;
                    param.Value = remarks;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = LDStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANCStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = ANCStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEIDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = HEIDStartDate;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANC";
                    param.DbType = DbType.Boolean;
                    param.Value = provideANC;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEID";
                    param.DbType = DbType.Boolean;
                    param.Value = provideHEID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Prophylaxis";
                    param.DbType = DbType.Boolean;
                    param.Value = provideProphylaxis;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ProphylaxisStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = prophylaxisDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ActivityDate";
                    param.DbType = DbType.DateTime;
                    param.Value = activityDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ProvideDBS";
                    param.DbType = DbType.Boolean;
                    param.Value = provideDBS;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Activated";
                    param.DbType = DbType.Boolean;
                    param.Value = actived;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Trained";
                    param.DbType = DbType.Boolean;
                    param.Value = trained;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@CreatedByUser";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityType";
                    param.DbType = DbType.Int32;
                    param.Value = facilityType;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Status";
                    param.DbType = DbType.Int32;
                    param.Value = status;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@CreateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);
                    #endregion

                    int affectedRows = -1;
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command);
                    okToContinue = (affectedRows > 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.FacilityDetailsInsert3(code, name, internalName, shortname, region, 
                        district, description, address, principalContact, remarks, LDStartDateTime, prophylaxisDateTime,
                        ANCStartDateTime, HEIDStartDate, provideANC, provideHEID, provideLD, provideProphylaxis,
                        activityDateTime, actived, trained, provideDBS, facilityType, supportingPartnerId, 
                        userSignature, status);
                    output = DataTransformation.Decrypt(output);
                    okToContinue = bool.Parse(output);
                    break;
            }
            return okToContinue;
        }

        [Obsolete("This method require too many details which are not used. Use another FacilityDetailsUpdate2", true)]
        public static bool FacilityDetailsUpdate(string oldCode, string code, string name, string shortname, int region, int district,
            string description, string address, string principalContact, int status, string remarks,
            DateTime PMTCTStartDateTime, DateTime LDStartDateTime, DateTime prophylaxisDateTime,
            DateTime ANCStartDateTime, DateTime HEIDStartDate, bool provideANC, bool provideHEID, bool providePMTCT,
            bool provideLD, bool provideProphylaxis, DateTime activeDateTime, DateTime inactiveDateTime, bool trained)
        {
            bool okToContinue = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"UPDATE Facilities SET FacCode = @FacCode, FacName = @FacName, FacShortName = @FacShortName, 
                        Region = @Region, District = @District, PMTCT = @PMTCT, LD = @LD, Description = @Description, 
                        Address = @Address, PrincipalContact = @PrincipalContact, Status = @Status, Remarks = @Remarks, 
                        PMTCTStartDate = @PMTCTStartDate, LDStartDate = @LDStartDate, ANCStartDate = @ANCStartDate,
                        HEIDStartDate = @HEIDStartDate, ANC = @ANC, HEID = @HEID, Prophylaxis = @Prophylaxis,
                        ProphylaxisStartDate = @ProphylaxisStartDate, ActiveDate = @ActiveDate, InactiveDate = @InactiveDate,
                        Trained = @Trained WHERE FacCode = @OldFacCode";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    #region Setting Command Parameters
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = code;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacName";
                    param.DbType = DbType.String;
                    param.Value = name;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacShortName";
                    param.DbType = DbType.String;
                    param.Value = shortname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = region;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.Int32;
                    param.Value = district;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PMTCT";
                    param.DbType = DbType.Boolean;
                    param.Value = providePMTCT;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LD";
                    param.DbType = DbType.Boolean;
                    param.Value = provideLD;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Description";
                    param.DbType = DbType.String;
                    param.Value = description;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Address";
                    param.DbType = DbType.String;
                    param.Value = address;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PrincipalContact";
                    param.DbType = DbType.String;
                    param.Value = principalContact;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Status";
                    param.DbType = DbType.Int32;
                    param.Value = status;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Remarks";
                    param.DbType = DbType.String;
                    param.Value = remarks;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PMTCTStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = PMTCTStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = LDStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANCStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = ANCStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEIDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = HEIDStartDate;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANC";
                    param.DbType = DbType.Boolean;
                    param.Value = provideANC;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEID";
                    param.DbType = DbType.Boolean;
                    param.Value = provideHEID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Prophylaxis";
                    param.DbType = DbType.Boolean;
                    param.Value = provideProphylaxis;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ProphylaxisStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = prophylaxisDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ActiveDate";
                    param.DbType = DbType.DateTime;
                    param.Value = activeDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@InactiveDate";
                    param.DbType = DbType.DateTime;
                    param.Value = inactiveDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@OldFacCode";
                    param.DbType = DbType.String;
                    param.Value = oldCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Trained";
                    param.DbType = DbType.Boolean;
                    param.Value = trained;
                    command.Parameters.Add(param);
                    #endregion

                    int affectedRows = -1;
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command, false);
                    okToContinue = (affectedRows > 0);

                    //// Updating expected reports
                    //command.CommandText = @"UPDATE ExpectedReports SET FacCode=@FacCode WHERE FacCode=@OldFacCode";
                    //GenericDataAccess.ExecuteNonQuery(command, false);

                    //// Updating ReceivedSMS table
                    //command.CommandText = @"UPDATE ReceivedSMS SET FacCode=@FacCode WHERE FacCode=@OldFacCode";
                    //GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating existing report data
                    command.CommandText = @"UPDATE ReportData SET Data=@FacCode WHERE Data=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating user access level
                    command.CommandText = @"UPDATE Users SET AccessLevelValue=@FacCode WHERE AccessLevelValue=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating registered phone number
                    command.CommandText = @"UPDATE ApprovedSMSCells SET FacCode=@FacCode WHERE FacCode=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.FacilityDetailsUpdate(oldCode, code, name, shortname, region, district, description,
                        address, principalContact, status, remarks, PMTCTStartDateTime, LDStartDateTime, prophylaxisDateTime,
                        ANCStartDateTime, HEIDStartDate, provideANC, provideHEID, providePMTCT, provideLD, provideProphylaxis,
                        activeDateTime, inactiveDateTime, trained);
                    output = DataTransformation.Decrypt(output);
                    okToContinue = bool.Parse(output);
                    break;
            }
            return okToContinue;
        }

        public static bool FacilityDetailsUpdate2(string oldCode, string code, string name, string internalName, 
            string shortname, int region, int district,
            string description, string address, string principalContact, string remarks, 
            DateTime LDStartDateTime, DateTime prophylaxisDateTime, DateTime ANCStartDateTime, DateTime HEIDStartDate, 
            bool provideANC, bool provideHEID, bool provideLD, bool provideProphylaxis,
            DateTime activityDateTime, bool actived, bool trained, bool provideDBS, 
            int facilityType, int supportingPartnerId, int actionUserId)
        {
            bool okToContinue = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"UPDATE Facilities SET FacCode = @FacCode, FacName = @FacName, FacShortName = @FacShortName, 
                        Region = @Region, District = @District, LD = @LD, Description = @Description, 
                        Address = @Address, PrincipalContact = @PrincipalContact, Remarks = @Remarks, 
                        LDStartDate = @LDStartDate, ANCStartDate = @ANCStartDate, FacilityType=@FacilityType,
                        HEIDStartDate = @HEIDStartDate, ANC = @ANC, HEID = @HEID, Prophylaxis = @Prophylaxis,
                        ProphylaxisStartDate = @ProphylaxisStartDate, ActiveDate = @ActiveDate, Activated = @Activated,
                        Trained = @Trained, ProvideDBS = @ProvideDBS, InternalName = @InternalName, 
                        UpdatedByUser=@UpdatedByUser, UpdateDate = @UpdateDate, SupportingPartnerId = @SupportingPartnerId 
                        WHERE FacCode = @OldFacCode";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    #region Setting Command Parameters
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = code;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacName";
                    param.DbType = DbType.String;
                    param.Value = name;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@InternalName";
                    param.DbType = DbType.String;
                    param.Value = internalName;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacShortName";
                    param.DbType = DbType.String;
                    param.Value = shortname;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = region;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.Int32;
                    param.Value = district;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LD";
                    param.DbType = DbType.Boolean;
                    param.Value = provideLD;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Description";
                    param.DbType = DbType.String;
                    param.Value = description;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Address";
                    param.DbType = DbType.String;
                    param.Value = address;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@PrincipalContact";
                    param.DbType = DbType.String;
                    param.Value = principalContact;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Remarks";
                    param.DbType = DbType.String;
                    param.Value = remarks;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@LDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = LDStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANCStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = ANCStartDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEIDStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = HEIDStartDate;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ANC";
                    param.DbType = DbType.Boolean;
                    param.Value = provideANC;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@HEID";
                    param.DbType = DbType.Boolean;
                    param.Value = provideHEID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Prophylaxis";
                    param.DbType = DbType.Boolean;
                    param.Value = provideProphylaxis;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ProphylaxisStartDate";
                    param.DbType = DbType.DateTime;
                    param.Value = prophylaxisDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ActiveDate";
                    param.DbType = DbType.DateTime;
                    param.Value = activityDateTime;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@OldFacCode";
                    param.DbType = DbType.String;
                    param.Value = oldCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Trained";
                    param.DbType = DbType.Boolean;
                    param.Value = trained;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@ProvideDBS";
                    param.DbType = DbType.Boolean;
                    param.Value = provideDBS;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdatedByUser";
                    param.DbType = DbType.Int32;
                    param.Value = actionUserId;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@UpdateDate";
                    param.DbType = DbType.DateTime;
                    param.Value = DateTime.Now;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacilityType";
                    param.DbType = DbType.Int32;
                    param.Value = facilityType;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Activated";
                    param.DbType = DbType.Boolean;
                    param.Value = actived;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    #endregion

                    int affectedRows = -1;
                    affectedRows = GenericDataAccess.ExecuteNonQuery(command, false);
                    okToContinue = (affectedRows > 0);

                    #region Updating Associated Tables
                    // Updating expected reports
                    command.CommandText = @"UPDATE ExpectedReports SET FacCode=@FacCode WHERE FacCode=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating ReceivedSMS table
                    command.CommandText = @"UPDATE ReceivedSMS SET FacCode=@FacCode WHERE FacCode=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating existing report data
                    command.CommandText = @"UPDATE ReportData SET Data=@FacCode WHERE Data=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating user access level
                    command.CommandText = @"UPDATE Users SET AccessLevelValue=@FacCode WHERE AccessLevelValue=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Updating registered phone number
                    command.CommandText = @"UPDATE ApprovedSMSCells SET FacCode=@FacCode WHERE FacCode=@OldFacCode";
                    GenericDataAccess.ExecuteNonQuery(command);
                    #endregion
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(actionUserId.ToString());
                    string output = webService.FacilityDetailsUpdate3(oldCode, code, name, internalName, shortname, region, district, description,
                        address, principalContact, remarks, LDStartDateTime, prophylaxisDateTime,
                        ANCStartDateTime, HEIDStartDate, provideANC, provideHEID, provideLD, provideProphylaxis,
                        activityDateTime, actived, trained, provideDBS, facilityType, supportingPartnerId, userSignature);
                    output = DataTransformation.Decrypt(output);
                    okToContinue = bool.Parse(output);
                    break;
            }
            return okToContinue;
        }

        public static void FacilityDetailsSaveExpectedReports(string code, DataTable expectedReports)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM ExpectedReports WHERE FacCode = @FacCode";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = code;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Inserting expected reports
                    command.CommandText = @"INSERT INTO ExpectedReports(FacCode, ReportID, ReportingStartDate, DirectEntry) 
                        VALUES(@FacCode, @ReportID, @ReportingStartDate, @DirectEntry)";
                    foreach (DataRow r in expectedReports.Rows)
                    {
                        int reportId = Int32.Parse(r["ReportID"].ToString());
                        DateTime reportingStartDate = DateTime.Parse(r["ReportingStartDate"].ToString());
                        bool directEntry = Boolean.Parse(r["DirectEntry"].ToString());

                        command.Parameters.Clear();
                        param = command.CreateParameter();
                        param.ParameterName = "@FacCode";
                        param.DbType = DbType.String;
                        param.Value = code;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@ReportID";
                        param.DbType = DbType.Int32;
                        param.Value = reportId;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@ReportingStartDate";
                        param.DbType = DbType.DateTime;
                        param.Value = reportingStartDate;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@DirectEntry";
                        param.DbType = DbType.Boolean;
                        param.Value = directEntry;
                        command.Parameters.Add(param);
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:                    
                    int[] iReports = new int[expectedReports.Rows.Count];
                    DateTime[] dReports = new DateTime[expectedReports.Rows.Count];
                    bool[] bDirectEntry = new Boolean[expectedReports.Rows.Count];

                    int index = 0;
                    foreach (DataRow k in expectedReports.Rows)
                    {
                        iReports[index] = Int32.Parse(k["ReportID"].ToString());
                        dReports[index] = DateTime.Parse(k["ReportingStartDate"].ToString());
                        bDirectEntry[index] = Boolean.Parse(k["DirectEntry"].ToString());
                        index++;
                    }
                    webService.FacilityDetailsSaveExpectedReports2(code, iReports, dReports, bDirectEntry);                    
                    break;
            }
        }

        [Obsolete("This method does not provide enough information. Use another FacilityDetailsSaveExpectedReports that have date parameters", true)]
        public static void FacilityDetailsSaveExpectedReports(string code, List<int> expectedReports)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM ExpectedReports WHERE FacCode = @FacCode";

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = code;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    // Inserting expected reports
                    command.CommandText = @"INSERT INTO ExpectedReports(FacCode, ReportID, ReportingStartDate) 
                        VALUES(@FacCode, @ReportID, @ReportingStartDate)";
                    foreach (int r in expectedReports)
                    {
                        command.Parameters.Clear();
                        param = command.CreateParameter();
                        param.ParameterName = "@FacCode";
                        param.DbType = DbType.String;
                        param.Value = code;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@ReportID";
                        param.DbType = DbType.Int32;
                        param.Value = r;
                        command.Parameters.Add(param);
                        
                        //TODO: This is totally bad idea, but quick solution is needed. I'm under pressure here
                        param = command.CreateParameter();
                        param.ParameterName = "@ReportingStartDate";
                        param.DbType = DbType.DateTime;
                        param.Value = DateTime.Parse("2012-10-01");
                        command.Parameters.Add(param);
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    int[] reports = new int[expectedReports.Count];
                    for (int i = 0; i < expectedReports.Count; i++) reports[i] = expectedReports[i];
                    webService.FacilityDetailsSaveExpectedReports(code, reports);
                    break;
            }
        }

        public static bool FacilityDetailsCanDeleteFacility(string code)
        {
            bool status = false;
            DbCommand command = null;
            DbParameter parameter = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT COUNT(Data) AS ReportDataCount FROM ReportData WHERE (Data = @FacCode)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = code;
                    command.Parameters.Add(parameter);
                    string output = GenericDataAccess.ExecuteScalar(command);
                    int count = int.Parse(output);
                    status = (count < 1);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT COUNT(Data) AS ReportDataCount FROM ReportData WHERE (Data = @FacCode)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = code;
                    command.Parameters.Add(parameter);
                    string output2 = GenericDataAccess.ExecuteScalar(command);
                    int count2 = int.Parse(output2);
                    status = (count2 < 1);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string data = webService.FacilityDetailsCanDeleteFacility(code);
                    data = DataTransformation.Decrypt(data);
                    status = bool.Parse(data);
                    break;
            }
            return status;
        }

        public static bool FacilityDetailsDelete(string facilityCode)
        {
            bool status = false;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"DELETE FROM Facilities WHERE FacCode = @FacCode";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    int affectedRows = GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"DELETE FROM ExpectedReports WHERE FacCode = @FacCode";
                    GenericDataAccess.ExecuteNonQuery(command);
                    status = (affectedRows > 0);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.FacilityDetailsDelete(facilityCode);
                    output = DataTransformation.Decrypt(output);
                    status = bool.Parse(output);
                    break;
            }
            return status;
        }

        public static DataTable GetFacilityTypes()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilityTypes != null) return cache_FacilityTypes;
            }
            DataTable dataTable = null;
            DbCommand command = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT TypeId, TypeName, TypeDescription FROM FacilityType";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT TypeId, TypeName, TypeDescription FROM FacilityType";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command, false);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityTypes();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_FacilityTypes = dataTable;
            return dataTable;
        }
        #endregion

        #region FacilityManagement
        private static DataTable _GetAllFacitiesStatus = null;
        public static DataTable GetAllFacilitiesStatus()
        {
            //if (AppConfiguration.DataCached)
            //{
            //    if (cache_AllFacilities != null) return cache_AllFacilities;
            //}

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        ORDER BY [Facility Name] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        ORDER BY [FacName] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    if (_GetAllFacitiesStatus != null) return _GetAllFacitiesStatus;
                    
                    string output = webService.GetAllFacilitiesStatus();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            //if (AppConfiguration.DataCached) cache_AllFacilities = dataTable;
            _GetAllFacitiesStatus = dataTable;
            return dataTable;
        }

        public static DataTable GetAllFacilitiesStatus(int supportingPartnerId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllFacilities != null) return cache_AllFacilities;
            }

            DataTable dataTable = null;
            DbParameter param = null;
            DbCommand command = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId) ORDER BY [Facility Name] ASC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE (Facilities.SupportingPartnerId = @SupportingPartnerId) ORDER BY [FacName] ASC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesStatusBySupportingPartner(supportingPartnerId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_AllFacilities = dataTable;
            return dataTable;
        }

        public static DataTable GetAllRegionFacilitiesStatus(int regionID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllFacilitiesByRegion.ContainsKey(regionID)) 
                    return cache_AllFacilitiesByRegion[regionID];
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE Facilities.Region=@Region";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE Facilities.Region=@Region";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllRegionFacilitiesStatus(regionID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_AllFacilitiesByRegion[regionID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAllRegionFacilitiesStatus(int regionID, int supportingPartnerId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllFacilitiesByRegion.ContainsKey(regionID))
                    return cache_AllFacilitiesByRegion[regionID];
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE (Facilities.Region=@Region) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE (Facilities.Region=@Region) AND (Facilities.SupportingPartnerId = @SupportingPartnerId)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@Region";
                    param.DbType = DbType.Int32;
                    param.Value = regionID;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@SupportingPartnerId";
                    param.DbType = DbType.Int32;
                    param.Value = supportingPartnerId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllRegionFacilitiesStatusBySupportingPartner(regionID, 
                        supportingPartnerId);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_AllFacilitiesByRegion[regionID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAllDistrictFacilitiesStatus(int districtID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AllFacilitiesByDistrict.ContainsKey(districtID)) 
                    return cache_AllFacilitiesByDistrict[districtID];
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner]  
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE Facilities.District=@DistrictID";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE Facilities.District=@DistrictID";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@DistrictID";
                    param.DbType = DbType.Int32;
                    param.Value = districtID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllDistrictFacilitiesStatus(districtID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AllFacilitiesByDistrict[districtID] = dataTable;
            return dataTable;
        }

        public static DataTable GetFacilityStatus(string facilityCode)
        {
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner] 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE Facilities.FacCode=@FacCode";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained
                        Facilities.SupportingPartnerId, SupportingPartners.Name AS [Supporting Partner]  
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo INNER JOIN
                        SupportingPartners ON Facilities.SupportingPartnerId = SupportingPartners.Id
                        WHERE Facilities.FacCode=@FacCode";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityStatus(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetOtherSystemsFacilityDetails(int systemId, string internalFacilityCode, int requestingUserId)
        {
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT [SystemId], [InternalFacilityCode], [FacilityCode], [FacilityName], 
                        [DistrictName], [RegionName] FROM [OtherSystemsFacilityDetails]
                        WHERE [InternalFacilityCode]=@InternalFacilityCode AND [SystemId]=@SystemId";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@InternalFacilityCode";
                    param.DbType = DbType.String;
                    param.Value = internalFacilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SystemId";
                    param.DbType = DbType.Int32;
                    param.Value = systemId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT [SystemId], [InternalFacilityCode], [FacilityCode], [FacilityName], 
                        [DistrictName], [RegionName] FROM [OtherSystemsFacilityDetails]
                        WHERE [InternalFacilityCode]=@InternalFacilityCode AND [SystemId]=@SystemId";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@InternalFacilityCode";
                    param.DbType = DbType.String;
                    param.Value = internalFacilityCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SystemId";
                    param.DbType = DbType.Int32;
                    param.Value = systemId;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string userSignature = DataTransformation.Encrypt(requestingUserId.ToString());
                    string output = webService.GetOtherSystemsFacilityDetails(systemId, internalFacilityCode, userSignature);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        #region Not Applicable
        public static DataTable GetFacilitiesBySupportingPartner(int supportingPartnerId)
        {
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo 
                        WHERE (Facilities.SupportingPartnerId = @PartnerId) ORDER BY [Facility Name] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo 
                        WHERE (Facilities.SupportingPartnerId = @PartnerId) ORDER BY [FacName] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    //string output = webService.GetAllFacilitiesStatus();
                    //dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            return dataTable;
        }

        public static DataTable GetDistrictsBySupportingPartner(int supportingPartnerId)
        {
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo ORDER BY [Facility Name] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo ORDER BY [FacName] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesStatus();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            return dataTable;
        }

        public static DataTable GetRegionsBySupportingPartner(int supportingPartnerId)
        {
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        CASE Facilities.Status WHEN 1 THEN 'ACTIVE' ELSE 'INACTIVE' END AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId 
                        FROM Facilities INNER JOIN District ON Facilities.District = District.DistrictNo 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo ORDER BY [Facility Name] ASC";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Facilities.FacCode AS [Facility Code], Facilities.FacName AS [Facility Name], 
                        IIF(Facilities.Status = 1, 'ACTIVE', 'INACTIVE') AS [Status], 
                        District.District AS [District Name], Region.RegionName AS [Region Name], Facilities.Trained,
                        Facilities.SupportingPartnerId
                        FROM (Facilities INNER JOIN District ON Facilities.District = District.DistrictNo) 
                        INNER JOIN Region ON District.RegionNo = Region.RegionNo ORDER BY [FacName] ASC";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetAllFacilitiesStatus();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            return dataTable;
        }
        #endregion
        #endregion

        #region SMSReminder
        public static void SendSMSReminderWithPhoneNumbers(int reportID, int year, int period, string message, 
            List<List<string>> facilitiesPhoneNumbers, List<string> facilitiesCodes, bool repeat)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    if (String.IsNullOrEmpty(message)) return;
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"INSERT INTO SendSMSQueue([SenderNum], [TxtDetails]) VALUES(@SenderNum, @TxtDetails)";

                    for (int i = 0; i < facilitiesPhoneNumbers.Count; i++)
                    {
                        List<string> facilityNumbers = facilitiesPhoneNumbers[i];
                        string facilityCode = facilitiesCodes[i];

                        bool alreadSent = IsReminderSent(facilityCode, year, period, reportID);
                        if (alreadSent)
                        {
                            if (!repeat) continue;
                        }
                        else
                        {
                            InsertReminderTrackingInfo(facilityCode, year, period, reportID);
                        }

                        foreach (string number in facilityNumbers)
                        {
                            command.Parameters.Clear();
                            DbParameter param = command.CreateParameter();
                            param.ParameterName = "@SenderNum";
                            param.DbType = DbType.String;
                            param.Value = number;
                            command.Parameters.Add(param);

                            param = command.CreateParameter();
                            param.ParameterName = "@TxtDetails";
                            param.DbType = DbType.String;
                            param.Value = message;
                            command.Parameters.Add(param);
                            GenericDataAccess.ExecuteNonQuery(command, false);
                        }
                    }
                    if (command.Connection.State == ConnectionState.Open) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    int facilityCount = facilitiesPhoneNumbers.Count;
                    string[][] sfacilitiesPhoneNumbers = new string[facilityCount][];
                    for (int i = 0; i < facilityCount; i++)
                    {
                        List<string> numbers = facilitiesPhoneNumbers[i];
                        int numberCount = numbers.Count;
                        sfacilitiesPhoneNumbers[i] = new string[numberCount];
                        for (int j = 0; j < numberCount; j++) sfacilitiesPhoneNumbers[i][j] = facilitiesPhoneNumbers[i][j];
                    }

                    int codesCount = facilitiesCodes.Count;
                    string[] sfacilitiesCodes = new string[codesCount];
                    for (int i = 0; i < codesCount; i++) sfacilitiesCodes[i] = facilitiesCodes[i];

                    webService.SendSMSReminderWithPhoneNumbers(reportID, year, period, message, 
                        sfacilitiesPhoneNumbers, sfacilitiesCodes, repeat);
                    break;
            }            
        }

        public static void SendSMSReminder(int reportID, int year, int period, string message, 
            List<string> numbersToExclude, List<string> facilitiesCodes, bool repeat)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"INSERT INTO SendSMSQueue([SenderNum], [TxtDetails]) 
                        VALUES(@SenderNum, @TxtDetails)";

                    foreach (string facility in facilitiesCodes)
                    {
                        bool alreadySent = IsReminderSent(facility, year, period, reportID);
                        if (alreadySent)
                        {
                            if (!repeat) continue;
                        }
                        else
                        {
                            InsertReminderTrackingInfo(facility, year, period, reportID);
                        }

                        // Getting all users who receive SMS.
                        DataTable registeredUserNumbers = GetRegisteredReportingUsers(facility);
                        foreach (DataRow row in registeredUserNumbers.Rows)
                        {
                            string number = row["Cell number"].ToString();
                            bool canReceive = Boolean.Parse(row["Send SMS"].ToString());
                            if (canReceive)
                            {
                                bool notExcluded = true;
                                foreach (string excludedNumber in numbersToExclude)
                                {
                                    if (excludedNumber == number)
                                    {
                                        notExcluded = false;
                                        break;
                                    }
                                }
                                if (notExcluded)
                                {
                                    command.Parameters.Clear();
                                    DbParameter param = command.CreateParameter();
                                    param.ParameterName = "@SenderNum";
                                    param.DbType = DbType.String;
                                    param.Value = number;
                                    command.Parameters.Add(param);

                                    param = command.CreateParameter();
                                    param.ParameterName = "@TxtDetails";
                                    param.DbType = DbType.String;
                                    param.Value = message;
                                    command.Parameters.Add(param);
                                    GenericDataAccess.ExecuteNonQuery(command, false);
                                }
                            }
                        }
                    }
                    if (command.Connection.State == ConnectionState.Open) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    int count = facilitiesCodes.Count;
                    string[] sFacilitiesCodes = new string[count];
                    for (int i = 0; i < count; i++) sFacilitiesCodes[i] = facilitiesCodes[i];

                    count = numbersToExclude.Count;
                    string[] sNumbersToExclude = new string[count];
                    for (int i = 0; i < count; i++) sNumbersToExclude[i] = numbersToExclude[i];
                    webService.SendSMSReminder(reportID, year, period, message, sNumbersToExclude, sFacilitiesCodes, repeat);
                    break;
            }
        }

        private static bool IsReminderSent(string facilityCode, int year, int period, int reportID)
        {
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = @"SELECT COUNT(*) AS [count] FROM SMSReminderTracker WHERE [YEAR]=@Year 
                AND [Period]=@Period AND [ReportID]=@ReportID AND [FacCode]=@FacCode";

            DbParameter param = command.CreateParameter();
            param.ParameterName = "@FacCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);

            string output = GenericDataAccess.ExecuteScalar(command);
            int count = int.Parse(output);
            return (count == 1);
        }

        private static void InsertReminderTrackingInfo(string facilityCode, int year, int period, int reportID)
        {
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandType = CommandType.Text;
            command.CommandText = @"INSERT INTO SMSReminderTracker ([FacCode], [Year], [Period], ReportID) 
                VALUES(@FacCode, @Year, @Period, @ReportID)";

            DbParameter param = command.CreateParameter();
            param.ParameterName = "@FacCode";
            param.DbType = DbType.String;
            param.Value = facilityCode;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Year";
            param.DbType = DbType.Int32;
            param.Value = year;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@Period";
            param.DbType = DbType.Int32;
            param.Value = period;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@ReportID";
            param.DbType = DbType.Int32;
            param.Value = reportID;
            command.Parameters.Add(param);
            GenericDataAccess.ExecuteNonQuery(command);            
        }

        public static DataTable GetReportingStatus(string facilityCode, int period, int year)
        {
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    string query = @"SELECT Report.RepID, Report.ReportName, Report.RepVersion, 
                        (SELECT  CASE COUNT(RepID) WHEN 0 THEN 'NOT SENT' ELSE 'SENT' END AS Expr1
                        FROM ReceivedSMS WHERE (RepID = exp.ReportID) AND (Period = @Period) AND (Year = @Year) AND 
                        (FacCode = @FacCode)) AS Status FROM ExpectedReports AS exp INNER JOIN Report ON exp.ReportID = Report.RepID
                        WHERE (exp.FacCode = @FacCode) UNION SELECT RepID, ReportName, RepVersion, 'NOT EXPECTED' AS Status 
                        FROM Report AS Report_1 WHERE (RepID < 90000) AND (RepID NOT IN (SELECT ReportID FROM 
                        ExpectedReports WHERE (FacCode = @FacCode)))";

                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);
                    
                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Report.RepID, Report.ReportName, Report.RepVersion, 
                        (SELECT  IIF(COUNT(RepID) = 0, 'NOT SENT', 'SENT') AS Expr1
                        FROM ReceivedSMS WHERE (RepID = exp.ReportID) AND (Period = @Period) AND (Year = @Year) AND 
                        (FacCode = @FacCode)) AS Status FROM ExpectedReports AS exp INNER JOIN Report ON exp.ReportID = Report.RepID
                        WHERE (exp.FacCode = @FacCode) UNION SELECT RepID, ReportName, RepVersion, 'NOT EXPECTED' AS Status 
                        FROM Report AS Report_1 WHERE (RepID < 90000) AND (RepID NOT IN (SELECT ReportID FROM 
                        ExpectedReports WHERE (FacCode = @FacCode)))";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);                    

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetReportingStatus(facilityCode, period, year);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            return dataTable;
        }

        public static DataTable GetRegisteredReportingUsers(string facilityCode)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_RegisteredReportingUsers.ContainsKey(facilityCode))
                    return cache_RegisteredReportingUsers[facilityCode];
            }

            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name AS [Full name], UserTitle.Name AS [User Title],
                        ApprovedSMSCells.CellNum AS [Cell number], ApprovedSMSCells.SendSMS AS [Send SMS] 
                        FROM ApprovedSMSCells LEFT OUTER JOIN UserTitle ON ApprovedSMSCells.TitleID = UserTitle.TitleID 
                        WHERE ((ApprovedSMSCells.Deleted <> 1) OR (ApprovedSMSCells.Deleted IS NULL)) 
                        AND (ApprovedSMSCells.FacCode = @FacCode)";

                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name AS [Full name], UserTitle.Name AS [User Title],
                        ApprovedSMSCells.CellNum AS [Cell number], ApprovedSMSCells.SendSMS AS [Send SMS] 
                        FROM ApprovedSMSCells LEFT OUTER JOIN UserTitle ON ApprovedSMSCells.TitleID = UserTitle.TitleID 
                        WHERE ((ApprovedSMSCells.Deleted <> 1) OR (ApprovedSMSCells.Deleted IS NULL)) 
                        AND (ApprovedSMSCells.FacCode = @FacCode)";

                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegisteredReportingUsers(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_RegisteredReportingUsers[facilityCode] = dataTable;
            return dataTable;
        }

        /// <summary>
        /// Save the list of registered users in the facility so that they can receive reminders
        /// </summary>
        /// <param name="facilityCode">Facility</param>
        /// <param name="numbers">List of numbers which will receive SMS reminders</param>
        public static void SaveReminderReceiver(string facilityCode, List<string> numbers)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"UPDATE ApprovedSMSCells SET SendSMS='FALSE' 
                        WHERE ((ApprovedSMSCells.Deleted <> 1) OR (ApprovedSMSCells.Deleted IS NULL)) 
                        AND (ApprovedSMSCells.FacCode = @FacCode)";
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = facilityCode;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    command.CommandText = @"UPDATE ApprovedSMSCells SET SendSMS='TRUE' 
                        WHERE ((ApprovedSMSCells.Deleted <> 1) OR (ApprovedSMSCells.Deleted IS NULL)) 
                        AND (ApprovedSMSCells.FacCode = @FacCode) AND (ApprovedSMSCells.CellNum = @CellNum)";
                    foreach (string number in numbers)
                    {
                        command.Parameters.Clear();
                        param = command.CreateParameter();
                        param.ParameterName = "@FacCode";
                        param.DbType = DbType.String;
                        param.Value = facilityCode;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@CellNum";
                        param.DbType = DbType.String;
                        param.Value = number;
                        command.Parameters.Add(param);
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    int count = numbers.Count;
                    string[] sNumbers = new string[count];
                    for (int i = 0; i < count; i++) sNumbers[i] = numbers[i];
                    webService.SaveReminderReceiver(facilityCode, sNumbers);
                    break;
            }
        }
        #endregion

        #region Assistance Assignement
        public static void AssignToUser(ReportLevel level, int userID, List<string> assignmentIDs)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string insertQueryTemplate = @"INSERT INTO Assistance(ApprovedCellNo, <LEVEL>) 
                        VALUES (@ApprovedCellNo, @Assignment)";            
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"DELETE FROM Assistance WHERE ApprovedCellNo = @ApprovedCellNo";
            
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command, false);

                    switch (level)
                    {
                        case ReportLevel.FACILITY:
                            command.CommandText = insertQueryTemplate.Replace("<LEVEL>", "FacCode");
                            break;

                        case ReportLevel.DISTRICT:
                            command.CommandText = insertQueryTemplate.Replace("<LEVEL>", "DistrictID");
                            break;

                        case ReportLevel.REGION:
                            command.CommandText = insertQueryTemplate.Replace("<LEVEL>", "RegionID");
                            break;
                    }

                    foreach (string assignment in assignmentIDs)
                    {
                        command.Parameters.Clear();
                        param = command.CreateParameter();
                        param.ParameterName = "@ApprovedCellNo";
                        param.DbType = DbType.Int32;
                        param.Value = userID;
                        command.Parameters.Add(param);

                        param = command.CreateParameter();
                        param.ParameterName = "@Assignment";
                        if (level == ReportLevel.FACILITY) param.DbType = DbType.String;
                        else param.DbType = DbType.Int32;
                        param.Value = assignment;
                        command.Parameters.Add(param);
                        GenericDataAccess.ExecuteNonQuery(command, false);
                    }
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string[] sAssignmentIDs = new string[assignmentIDs.Count];
                    for (int i = 0; i < assignmentIDs.Count; i++) sAssignmentIDs[i] = assignmentIDs[i];

                    IQServices.ReportLevel sLevel = IQServices.ReportLevel.NATION;
                    if (level == ReportLevel.FACILITY) sLevel = IQServices.ReportLevel.FACILITY;
                    if (level == ReportLevel.DISTRICT) sLevel = IQServices.ReportLevel.DISTRICT;
                    if (level == ReportLevel.REGION) sLevel = IQServices.ReportLevel.REGION;
                    
                    webService.AssignToUser(sLevel, userID, sAssignmentIDs);
                    break;
            }
            
        }

        public static DataTable GetAssignedRegions(int userToExclude)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceAssignedRegions.ContainsKey(userToExclude))
                    return cache_AssistanceAssignedRegions[userToExclude];
            }

            DataTable dataTable = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"SELECT DISTINCT Assistance.RegionID, Region.RegionName FROM Assistance INNER JOIN
                        Region ON Assistance.RegionID = Region.RegionNo WHERE (Assistance.RegionID IS NOT NULL)
                        AND (Assistance.ApprovedCellNo <> @UserToExclude)";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    DbParameter parameter = command.CreateParameter();
                    parameter.ParameterName = "@UserToExclude";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userToExclude;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetAssignedRegions(userToExclude);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AssistanceAssignedRegions[userToExclude] = dataTable;
            return dataTable;
        }

        public static DataTable GetSelectedUserAssignedRegions(int userID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceSelectedUserAssignedRegions.ContainsKey(userID))
                    return cache_AssistanceSelectedUserAssignedRegions[userID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT RegionID FROM Assistance WHERE ApprovedCellNo = @ApprovedCellNo 
                        AND RegionID IS NOT NULL";

                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT RegionID FROM Assistance WHERE ApprovedCellNo = @ApprovedCellNo 
                        AND RegionID IS NOT NULL";

                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetSelectedUserAssignedRegions(userID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AssistanceSelectedUserAssignedRegions[userID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAssignedRegions()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceAssignedAllRegions != null) return cache_AssistanceAssignedAllRegions;
            }

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DISTINCT Assistance.RegionID, Region.RegionName FROM Assistance INNER JOIN
                        Region ON Assistance.RegionID = Region.RegionNo WHERE (Assistance.RegionID IS NOT NULL)";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT DISTINCT Assistance.RegionID, Region.RegionName FROM Assistance INNER JOIN
                        Region ON Assistance.RegionID = Region.RegionNo WHERE (Assistance.RegionID IS NOT NULL)";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetAssignedAllRegions();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_AssistanceAssignedAllRegions = dataTable;
            return dataTable;
        }

        public static DataTable GetSelectedUserAssignedDistricts(int userID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceSelectedUserAssignedDistricts.ContainsKey(userID))
                    return cache_AssistanceSelectedUserAssignedDistricts[userID];
            }

            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DistrictID FROM Assistance WHERE ApprovedCellNo=@ApprovedCellNo AND 
                        DistrictID IS NOT NULL";
                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT DistrictID FROM Assistance WHERE ApprovedCellNo=@ApprovedCellNo AND 
                        DistrictID IS NOT NULL";
                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetSelectedUserAssignedDistricts(userID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_AssistanceSelectedUserAssignedDistricts[userID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAssignedDistricts()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceAssignedAllDistricts != null) return cache_AssistanceAssignedAllDistricts;
            }

            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DISTINCT Assistance.DistrictID, District.District FROM Assistance INNER JOIN
                        District ON Assistance.DistrictID = District.DistrictNo WHERE (Assistance.DistrictID IS NOT NULL)";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT DISTINCT Assistance.DistrictID, District.District FROM Assistance INNER JOIN
                        District ON Assistance.DistrictID = District.DistrictNo WHERE (Assistance.DistrictID IS NOT NULL)";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetAssignedAllDistricts();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AssistanceAssignedAllDistricts = dataTable;
            return dataTable;
        }

        public static DataTable GetAssignedDistricts(int userToExclude)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceAssignedDistricts.ContainsKey(userToExclude))
                    return cache_AssistanceAssignedDistricts[userToExclude];
            }
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT DISTINCT Assistance.DistrictID, District.District FROM Assistance INNER JOIN
                        District ON Assistance.DistrictID = District.DistrictNo WHERE (Assistance.DistrictID IS NOT NULL)
                        AND (Assistance.ApprovedCellNo <> @UserToExclude)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@UserToExclude";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userToExclude;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT DISTINCT Assistance.DistrictID, District.District FROM Assistance INNER JOIN
                        District ON Assistance.DistrictID = District.DistrictNo WHERE (Assistance.DistrictID IS NOT NULL)
                        AND (Assistance.ApprovedCellNo <> @UserToExclude)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@UserToExclude";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userToExclude;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetAssignedDistricts(userToExclude);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AssistanceAssignedDistricts[userToExclude] = dataTable;
            return dataTable;
        }

        public static DataTable GetAssignedFacilities()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceAssignedAllFacilities != null) return cache_AssistanceAssignedAllFacilities;
            }
            DataTable dataTable = null;
            string query = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Assistance.FacCode, Facilities.FacName FROM Assistance INNER JOIN
                        Facilities ON Assistance.FacCode = Facilities.FacCode WHERE (Assistance.FacCode IS NOT NULL)";
                    dataTable = GenericDataAccess.RunSelectQuery(query);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Assistance.FacCode, Facilities.FacName FROM Assistance INNER JOIN
                        Facilities ON Assistance.FacCode = Facilities.FacCode WHERE (Assistance.FacCode IS NOT NULL)";
                    DbCommand command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandText = query;
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetAssignedAllFacilities();
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AssistanceAssignedAllFacilities = dataTable;
            return dataTable;
        }

        public static DataTable GetSelectedUserAssignedFacilities(int userID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceSelectedUserAssignedFacilities.ContainsKey(userID))
                    return cache_AssistanceSelectedUserAssignedFacilities[userID];
            }
            DataTable dataTable = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT FacCode FROM Assistance WHERE ApprovedCellNo=@ApprovedCellNo 
                        AND FacCode IS NOT NULL";
                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = @"SELECT FacCode FROM Assistance WHERE ApprovedCellNo=@ApprovedCellNo 
                        AND FacCode IS NOT NULL";
                    param = command.CreateParameter();
                    param.ParameterName = "@ApprovedCellNo";
                    param.DbType = DbType.Int32;
                    param.Value = userID;
                    command.Parameters.Add(param);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetSelectedUserAssignedFacilities(userID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_AssistanceSelectedUserAssignedFacilities[userID] = dataTable;
            return dataTable;
        }

        public static DataTable GetAssignedFacilities(int userToExclude)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_AssistanceAssignedFacilities.ContainsKey(userToExclude))
                    return cache_AssistanceAssignedFacilities[userToExclude];
            }
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT Assistance.FacCode, Facilities.FacName FROM Assistance INNER JOIN
                        Facilities ON Assistance.FacCode = Facilities.FacCode WHERE (Assistance.FacCode IS NOT NULL)
                        AND (Assistance.ApprovedCellNo <> @UserToExclude)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@UserToExclude";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userToExclude;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT Assistance.FacCode, Facilities.FacName FROM Assistance INNER JOIN
                        Facilities ON Assistance.FacCode = Facilities.FacCode WHERE (Assistance.FacCode IS NOT NULL)
                        AND (Assistance.ApprovedCellNo <> @UserToExclude)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@UserToExclude";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = userToExclude;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.AssistanceGetAssignedFacilities(userToExclude);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }
            
            if (AppConfiguration.DataCached) cache_AssistanceAssignedFacilities[userToExclude] = dataTable;
            return dataTable;
        }

        public static DataTable GetFacilityAssignedUsers(string facilityCode)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_FacilitiesAssignedUsers.ContainsKey(facilityCode))
                    return cache_FacilitiesAssignedUsers[facilityCode];
            }
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name, ApprovedSMSCells.CellNum FROM Assistance INNER JOIN
                        ApprovedSMSCells ON Assistance.ApprovedCellNo = ApprovedSMSCells.ApprovedCellNo
                        WHERE (Assistance.FacCode = @FacCode)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = facilityCode;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name, ApprovedSMSCells.CellNum FROM Assistance INNER JOIN
                        ApprovedSMSCells ON Assistance.ApprovedCellNo = ApprovedSMSCells.ApprovedCellNo
                        WHERE (Assistance.FacCode = @FacCode)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@FacCode";
                    parameter.DbType = DbType.String;
                    parameter.Value = facilityCode;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetFacilityAssignedUsers(facilityCode);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_FacilitiesAssignedUsers[facilityCode] = dataTable;
            return dataTable;
        }

        public static DataTable GetRegionAssignedUsers(int regionID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_RegionsAssignedUsers.ContainsKey(regionID))
                    return cache_RegionsAssignedUsers[regionID];
            }
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name, ApprovedSMSCells.CellNum FROM Assistance INNER JOIN
                        ApprovedSMSCells ON Assistance.ApprovedCellNo = ApprovedSMSCells.ApprovedCellNo
                        WHERE (Assistance.RegionID = @RegionID)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name, ApprovedSMSCells.CellNum FROM Assistance INNER JOIN
                        ApprovedSMSCells ON Assistance.ApprovedCellNo = ApprovedSMSCells.ApprovedCellNo
                        WHERE (Assistance.RegionID = @RegionID)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@RegionID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = regionID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetRegionAssignedUsers(regionID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_RegionsAssignedUsers[regionID] = dataTable;
            return dataTable;
        }

        public static DataTable GetDistrictAssignedUsers(int districtID)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_DistrictsAssignedUsers.ContainsKey(districtID))
                    return cache_DistrictsAssignedUsers[districtID];
            }
            DataTable dataTable = null;
            string query = null;
            DbCommand command = null;
            DbParameter parameter = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name, ApprovedSMSCells.CellNum FROM Assistance INNER JOIN
                        ApprovedSMSCells ON Assistance.ApprovedCellNo = ApprovedSMSCells.ApprovedCellNo
                        WHERE (Assistance.DistrictID = @DistrictID)";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    query = @"SELECT ApprovedSMSCells.Name, ApprovedSMSCells.CellNum FROM Assistance INNER JOIN
                        ApprovedSMSCells ON Assistance.ApprovedCellNo = ApprovedSMSCells.ApprovedCellNo
                        WHERE (Assistance.DistrictID = @DistrictID)";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    
                    parameter = command.CreateParameter();
                    parameter.ParameterName = "@DistrictID";
                    parameter.DbType = DbType.Int32;
                    parameter.Value = districtID;
                    command.Parameters.Add(parameter);
                    dataTable = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetDistrictAssignedUsers(districtID);
                    dataTable = DataTransformation.Deserialize(output);
                    break;
            }

            if (AppConfiguration.DataCached) cache_DistrictsAssignedUsers[districtID] = dataTable;
            return dataTable;
        }

        #endregion

        #region Blocked Reports
        public static DataTable GetBlockedReports()
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_BlockedReports != null) return cache_BlockedReports;
            }
            DataTable blockedReports = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
//                    string query = @"SELECT ReceivedSMSNo, es.SenderNum, ac.Name, es.DateReceived, es.RepID, r.ReportName, 
//                        es.Year, es.Period, es.ErrMsg, es.TxtDetails, es.FacCode, f.FacName, rg.RegionName FROM ErrMsgSMS es
//                        INNER JOIN ApprovedSMSCells ac ON ac.CellNum = es.SenderNum INNER JOIN Report r on r.RepID = es.RepID
//                        INNER JOIN Facilities f on f.FacCode = es.FacCode INNER JOIN Region rg on rg.RegionNo = f.Region
//                        ORDER BY DateReceived DESC";
                    query = @"SELECT es.ReceivedSMSNo, es.SenderNum, ac.Name, es.DateReceived, 
                        es.RepID, r.ReportName, es.Year, es.Period, es.ErrMsg, es.TxtDetails, es.FacCode, 
                        f.FacName, rg.RegionName, District.District AS DistrictName FROM Region AS rg 
                        INNER JOIN Facilities AS f ON rg.RegionNo = f.Region INNER JOIN District 
                        ON f.District = District.DistrictNo RIGHT OUTER JOIN ErrMsgSMS AS es ON f.FacCode = es.FacCode 
                        LEFT OUTER JOIN Report AS r ON r.RepID = es.RepID LEFT OUTER JOIN 
                        ApprovedSMSCells AS ac ON ac.CellNum = es.SenderNum WHERE (es.SenderNum IN
                        (SELECT SenderNum FROM (SELECT SenderNum, COUNT(SenderNum) AS count
                        FROM ErrMsgSMS GROUP BY SenderNum) AS errorCount WHERE (count >= @MaxErrorCount))) 
                        AND es.Deleted<>1 OR es.Deleted IS NULL ORDER BY es.DateReceived DESC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@MaxErrorCount";
                    param.DbType = DbType.Int32;
                    param.Value = AppConfiguration.MaximumErrorTolerance;
                    command.Parameters.Add(param);
                    blockedReports = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    //TODO: Query of getting blocked report for access may miss some records due MS Access join support
                    //RESOLUTION: The query should be divided into subqueries.
                    query = @"SELECT ErrMsgSMS.ReceivedSMSNo, ErrMsgSMS.SenderNum, ApprovedSMSCells.Name, 
                        ErrMsgSMS.DateReceived, Report.RepID, Report.ReportName, ErrMsgSMS.Year, 
                        ErrMsgSMS.Period, ErrMsgSMS.ErrMsg, ErrMsgSMS.TxtDetails, ErrMsgSMS.FacCode, 
                        Facilities.FacName, Region.RegionName, District.District AS DistrictName
                        FROM (Report RIGHT JOIN (((Facilities INNER JOIN ErrMsgSMS ON 
                        Facilities.FacCode = ErrMsgSMS.FacCode) INNER JOIN Region ON 
                        Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                        Facilities.District = District.DistrictNo) ON Report.RepID = ErrMsgSMS.RepID) 
                        LEFT JOIN ApprovedSMSCells ON ErrMsgSMS.SenderNum = ApprovedSMSCells.CellNum 
                        WHERE (ErrMsgSMS.SenderNum IN (SELECT  SenderNum FROM 
                        (SELECT SenderNum, COUNT(SenderNum) AS [count]  FROM ErrMsgSMS GROUP BY SenderNum) 
                        AS errorCount WHERE ([count] >= @MaxErrorCount))) AND 
                        (ErrMsgSMS.Deleted<>1 OR ErrMsgSMS.Deleted IS NULL) ORDER BY ErrMsgSMS.DateReceived DESC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@MaxErrorCount";
                    param.DbType = DbType.Int32;
                    param.Value = AppConfiguration.MaximumErrorTolerance;
                    command.Parameters.Add(param);
                    blockedReports = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetBlockedReports();
                    blockedReports = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_BlockedReports = blockedReports;
            return blockedReports;
        }

        public static DataTable GetBlockedReportsByRegion(int regionId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_BlockedReports != null) return cache_BlockedReports;
            }
            DataTable blockedReports = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    //                    string query = @"SELECT ReceivedSMSNo, es.SenderNum, ac.Name, es.DateReceived, es.RepID, r.ReportName, 
                    //                        es.Year, es.Period, es.ErrMsg, es.TxtDetails, es.FacCode, f.FacName, rg.RegionName FROM ErrMsgSMS es
                    //                        INNER JOIN ApprovedSMSCells ac ON ac.CellNum = es.SenderNum INNER JOIN Report r on r.RepID = es.RepID
                    //                        INNER JOIN Facilities f on f.FacCode = es.FacCode INNER JOIN Region rg on rg.RegionNo = f.Region
                    //                        ORDER BY DateReceived DESC";
                    query = @"SELECT es.ReceivedSMSNo, es.SenderNum, ac.Name, es.DateReceived, 
                        es.RepID, r.ReportName, es.Year, es.Period, es.ErrMsg, es.TxtDetails, es.FacCode, 
                        f.FacName, rg.RegionName, District.District AS DistrictName FROM Region AS rg 
                        INNER JOIN Facilities AS f ON rg.RegionNo = f.Region INNER JOIN District 
                        ON f.District = District.DistrictNo RIGHT OUTER JOIN ErrMsgSMS AS es ON f.FacCode = es.FacCode 
                        LEFT OUTER JOIN Report AS r ON r.RepID = es.RepID LEFT OUTER JOIN 
                        ApprovedSMSCells AS ac ON ac.CellNum = es.SenderNum WHERE (es.SenderNum IN
                        (SELECT SenderNum FROM (SELECT SenderNum, COUNT(SenderNum) AS count
                        FROM ErrMsgSMS GROUP BY SenderNum) AS errorCount WHERE (count >= @MaxErrorCount))) 
                        AND (es.Deleted<>1 OR es.Deleted IS NULL) AND (rg.RegionNo = @RegionNo) ORDER BY es.DateReceived DESC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@MaxErrorCount";
                    param.DbType = DbType.Int32;
                    param.Value = AppConfiguration.MaximumErrorTolerance;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RegionNo";
                    param.DbType = DbType.Int32;
                    param.Value = regionId;
                    command.Parameters.Add(param);
                    blockedReports = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    //TODO: Query of getting blocked report for access may miss some records due MS Access join support
                    //RESOLUTION: The query should be divided into subqueries.
                    query = @"SELECT ErrMsgSMS.ReceivedSMSNo, ErrMsgSMS.SenderNum, ApprovedSMSCells.Name, 
                        ErrMsgSMS.DateReceived, Report.RepID, Report.ReportName, ErrMsgSMS.Year, 
                        ErrMsgSMS.Period, ErrMsgSMS.ErrMsg, ErrMsgSMS.TxtDetails, ErrMsgSMS.FacCode, 
                        Facilities.FacName, Region.RegionName, District.District AS DistrictName
                        FROM (Report RIGHT JOIN (((Facilities INNER JOIN ErrMsgSMS ON 
                        Facilities.FacCode = ErrMsgSMS.FacCode) INNER JOIN Region ON 
                        Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                        Facilities.District = District.DistrictNo) ON Report.RepID = ErrMsgSMS.RepID) 
                        LEFT JOIN ApprovedSMSCells ON ErrMsgSMS.SenderNum = ApprovedSMSCells.CellNum 
                        WHERE (ErrMsgSMS.SenderNum IN (SELECT  SenderNum FROM 
                        (SELECT SenderNum, COUNT(SenderNum) AS [count]  FROM ErrMsgSMS GROUP BY SenderNum) 
                        AS errorCount WHERE ([count] >= @MaxErrorCount))) AND 
                        (ErrMsgSMS.Deleted<>1) AND (rg.RegionNo = @RegionNo) OR es.Deleted IS NULL ORDER BY ErrMsgSMS.DateReceived DESC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@MaxErrorCount";
                    param.DbType = DbType.Int32;
                    param.Value = AppConfiguration.MaximumErrorTolerance;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RegionNo";
                    param.DbType = DbType.Int32;
                    param.Value = regionId;
                    command.Parameters.Add(param);
                    blockedReports = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetBlockedReportsByRegion(regionId);
                    blockedReports = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_BlockedReports = blockedReports;
            return blockedReports;
        }

        public static DataTable GetBlockedReportsByDistrict(int districtId)
        {
            if (AppConfiguration.DataCached)
            {
                if (cache_BlockedReports != null) return cache_BlockedReports;
            }
            DataTable blockedReports = null;
            string query = null;
            DbCommand command = null;
            DbParameter param = null;
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    //                    string query = @"SELECT ReceivedSMSNo, es.SenderNum, ac.Name, es.DateReceived, es.RepID, r.ReportName, 
                    //                        es.Year, es.Period, es.ErrMsg, es.TxtDetails, es.FacCode, f.FacName, rg.RegionName FROM ErrMsgSMS es
                    //                        INNER JOIN ApprovedSMSCells ac ON ac.CellNum = es.SenderNum INNER JOIN Report r on r.RepID = es.RepID
                    //                        INNER JOIN Facilities f on f.FacCode = es.FacCode INNER JOIN Region rg on rg.RegionNo = f.Region
                    //                        ORDER BY DateReceived DESC";
                    query = @"SELECT es.ReceivedSMSNo, es.SenderNum, ac.Name, es.DateReceived, 
                        es.RepID, r.ReportName, es.Year, es.Period, es.ErrMsg, es.TxtDetails, es.FacCode, 
                        f.FacName, rg.RegionName, District.District AS DistrictName FROM Region AS rg 
                        INNER JOIN Facilities AS f ON rg.RegionNo = f.Region INNER JOIN District 
                        ON f.District = District.DistrictNo RIGHT OUTER JOIN ErrMsgSMS AS es ON f.FacCode = es.FacCode 
                        LEFT OUTER JOIN Report AS r ON r.RepID = es.RepID LEFT OUTER JOIN 
                        ApprovedSMSCells AS ac ON ac.CellNum = es.SenderNum WHERE (es.SenderNum IN
                        (SELECT SenderNum FROM (SELECT SenderNum, COUNT(SenderNum) AS count
                        FROM ErrMsgSMS GROUP BY SenderNum) AS errorCount WHERE (count >= @MaxErrorCount))) 
                        AND (es.Deleted<>1 OR es.Deleted IS NULL) AND (District.DistrictNo = @District)  ORDER BY es.DateReceived DESC";
                    command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@MaxErrorCount";
                    param.DbType = DbType.Int32;
                    param.Value = AppConfiguration.MaximumErrorTolerance;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.Int32;
                    param.Value = districtId;
                    command.Parameters.Add(param);
                    blockedReports = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                    //TODO: Query of getting blocked report for access may miss some records due MS Access join support
                    //RESOLUTION: The query should be divided into subqueries.
                    query = @"SELECT ErrMsgSMS.ReceivedSMSNo, ErrMsgSMS.SenderNum, ApprovedSMSCells.Name, 
                        ErrMsgSMS.DateReceived, Report.RepID, Report.ReportName, ErrMsgSMS.Year, 
                        ErrMsgSMS.Period, ErrMsgSMS.ErrMsg, ErrMsgSMS.TxtDetails, ErrMsgSMS.FacCode, 
                        Facilities.FacName, Region.RegionName, District.District AS DistrictName
                        FROM (Report RIGHT JOIN (((Facilities INNER JOIN ErrMsgSMS ON 
                        Facilities.FacCode = ErrMsgSMS.FacCode) INNER JOIN Region ON 
                        Facilities.Region = Region.RegionNo) INNER JOIN District ON 
                        Facilities.District = District.DistrictNo) ON Report.RepID = ErrMsgSMS.RepID) 
                        LEFT JOIN ApprovedSMSCells ON ErrMsgSMS.SenderNum = ApprovedSMSCells.CellNum 
                        WHERE (ErrMsgSMS.SenderNum IN (SELECT  SenderNum FROM 
                        (SELECT SenderNum, COUNT(SenderNum) AS [count]  FROM ErrMsgSMS GROUP BY SenderNum) 
                        AS errorCount WHERE ([count] >= @MaxErrorCount))) AND 
                        (ErrMsgSMS.Deleted<>1) AND (District.DistrictNo = @District) OR es.Deleted IS NULL ORDER BY ErrMsgSMS.DateReceived DESC";
                    command = GenericDataAccess.CreateCacheDBCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;
                    param = command.CreateParameter();
                    param.ParameterName = "@MaxErrorCount";
                    param.DbType = DbType.Int32;
                    param.Value = AppConfiguration.MaximumErrorTolerance;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@District";
                    param.DbType = DbType.Int32;
                    param.Value = districtId;
                    command.Parameters.Add(param);
                    blockedReports = GenericDataAccess.ExecuteSelectCommand(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    string output = webService.GetBlockedReportsByDistrict(districtId);
                    blockedReports = DataTransformation.Deserialize(output);
                    break;
            }
            if (AppConfiguration.DataCached) cache_BlockedReports = blockedReports;
            return blockedReports;
        }

        public static void DeleteBlockedUserReport(string senderNumber)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"DELETE FROM ErrMsgSMS WHERE SenderNum=@SenderNum";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@SenderNum";
                    param.DbType = DbType.String;
                    param.Value = senderNumber;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    webService.DeleteBlockedUserReport(senderNumber);
                    break;
            }
        }

        public static void DeleteBlockedReport(int reportID, string FacCode, int period, int year)
        {
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    string query = @"DELETE FROM ErrMsgSMS WHERE FacCode=@FacCode AND Year=@Year AND 
                        Period=@Period AND RepID=@RepID";
                    DbCommand command = GenericDataAccess.CreateCommand();
                    command.CommandType = CommandType.Text;
                    command.CommandText = query;

                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@FacCode";
                    param.DbType = DbType.String;
                    param.Value = FacCode;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Year";
                    param.DbType = DbType.Int32;
                    param.Value = year;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@Period";
                    param.DbType = DbType.Int32;
                    param.Value = period;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@RepID";
                    param.DbType = DbType.Int32;
                    param.Value = reportID;
                    command.Parameters.Add(param);
                    GenericDataAccess.ExecuteNonQuery(command);
                    break;

                case DataAccessMethod.WEB_SERVICES:
                    webService.DeleteBlockedReport(reportID, FacCode, period, year);
                    break;
            }            
        }

        public static DataTable GetBlockedNumbers()
        {
            string query = @"SELECT PhoneNumber FROM BlockedNumbers";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            return dataTable;

        }

        public static void RemoveBlockedNumber(string phoneNumber)
        {
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandText = @"DELETE FROM BlockedNumbers WHERE PhoneNumber=@PhoneNumber";
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@PhoneNumber";
            param.DbType = DbType.String;
            param.Value = phoneNumber;
            command.Parameters.Add(param);
            GenericDataAccess.ExecuteNonQuery(command);
        }

        public static void ClearAllBlockedNumbers()
        {
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandText = @"DELETE FROM BlockedNumbers WHERE PhoneNumber=@PhoneNumber";

            DataTable blocked = GetBlockedNumbers();
            foreach (DataRow row in blocked.Rows)
            {
                string phoneNumber = row["SenderNum"].ToString();
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@PhoneNumber";
                param.DbType = DbType.String;                
                param.Value = phoneNumber;
                command.Parameters.Add(param);
                GenericDataAccess.ExecuteNonQuery(command, false);
            }
            if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();      
        }

        public static void AddBlockedNumber(string phoneNumber)
        {
            RemoveBlockedNumber(phoneNumber);
            
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandText = @"INSERT INTO BlockedNumbers(PhoneNumber) VALUES(@PhoneNumber)";
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@PhoneNumber";
            param.DbType = DbType.String;
            param.Value = phoneNumber;
            command.Parameters.Add(param);
            GenericDataAccess.ExecuteNonQuery(command);
        }

        public static bool IsNumberBlocked(string phoneNumber)
        {
            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandText = @"SELECT COUNT(PhoneNumber) FROM BlockedNumbers WHERE PhoneNumber = @PhoneNumber";
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@PhoneNumber";
            param.DbType = DbType.String;
            param.Value = phoneNumber;
            command.Parameters.Add(param);
            string count = GenericDataAccess.ExecuteScalar(command);
            int iCount = Int32.Parse(count);
            if (iCount == 1) return true;
            else return false;
        }
        #endregion

        #region Data Capture
        public static ReportingMessage SendReport(string senderNum, string reportingText/*, string userSignature*/, 
            bool allowingSameMonthReporting, string comments = null)
        {
            //throw new Exception("Data Modification is not allowed at this time. Try again later after APR");

            SMSReportingFormat SMSFormat = SMSReportingFormat.RESTRICTIVE;
            DataInputingMethod inputMethod = DataInputingMethod.DESKTOP_DATA_CAPTURE;

            ReportingMessage reportingMessage = new ReportingMessage();
            switch (AppConfiguration.AccessMethod)
            {
                case DataAccessMethod.DIRECT_ACCESS:
                    ReportProcessor reportProcessor = null;
                    //string errorText = String.Empty;
                    ReportingMode reportingMode = ReportingMode.DEFAULT;
                    if (allowingSameMonthReporting) reportingMode |= ReportingMode.ALLOW_SAME_MONTH_REPORTING;
                    reportProcessor = new ReportProcessor(senderNum, reportingText, 
                        ReportingType.VALIDATION, reportingMode, SMSFormat, inputMethod, comments);
                    reportProcessor.ReportBussinessRulesFailed += ReportProcessor.HandleMTUHAMCReport;
                    reportProcessor.SavingReport += ReportProcessor.HandleInconsitentReports;
                    reportProcessor.Submit();
                    
                    //errorText = GetTranslationText("IQSMS", reportProcessor.ErrorTextLabelID);
                    reportingMessage.Message = reportProcessor.ErrorText;;
                    reportingMessage.Status = reportProcessor.ErrorTextLabelID;            
                    break;

                case DataAccessMethod.WEB_SERVICES:
                case DataAccessMethod.OFFLINE_DATA_ACCESS:
                case DataAccessMethod.OFFLINE_DIRECT_ACCESS:
                    string output = webService.SendReportWithComments(senderNum, reportingText, comments);//, userSignature);
                    DataTable dataTable = DataTransformation.Deserialize(output);
                    DataRow row = dataTable.Rows[0];
                    reportingMessage.Status = Int32.Parse(row["Status"].ToString());
                    reportingMessage.Message = row["Message"].ToString();
                    break;
            }
            return reportingMessage;
        }

        /// <summary>
        /// Directly upload the offline report data into the server.
        /// </summary>
        /// <param name="report"></param>
        /// <returns></returns>
        public static ReportingMessage SendReport(DataModels.Models.OfflineData.OfflineReport report)
        {
            ReportingMessage reportingMessage = new ReportingMessage();            
            string output = webService.SendReportWithComments(report.CreatedByUserName, report.ReportMessage, report.ReportComments);
            
            DataTable dataTable = DataTransformation.Deserialize(output);
            DataRow row = dataTable.Rows[0];
            reportingMessage.Status = Int32.Parse(row["Status"].ToString());
            reportingMessage.Message = row["Message"].ToString();
            return reportingMessage;
        }
        #endregion

        public static void ClearCache(DataCache cache)
        {
            switch (cache)
            {
                case DataCache.REPORTS_DETAILS:
                    cache_ExpectedReports = null;
                    cache_ReportDetails.Clear();
                    cache_ReportsCanBeDeleted.Clear();
                    cache_ReportDataLocations.Clear();
                    cache_ReportRules.Clear();
                    break;

                case DataCache.USERS_DETAILS:
                    cache_AllUsers = null;
                    break;

                case DataCache.REPORTS_BUSINESS_RULES:
                    cache_ReportRules.Clear();
                    break;

                case DataCache.ASSISTANCE_ASSIGNMENT:
                    cache_AssistanceAssignedAllRegions = null;
                    cache_AssistanceAssignedAllDistricts = null;
                    cache_AssistanceAssignedAllFacilities = null;
                    break;

                case DataCache.TRANSLATIONS:
                    cache_LanguageTranslationByLabelNo.Clear();
                    cache_AllLanguageTranslations.Clear();
                    break;

                case DataCache.BLOCKED_REPORTS:
                    cache_BlockedReports = null;
                    break;
            }
        }

        #region Public Properties
        public static int MINIMUM_DATA_COMPONENTS
        {
            get
            {
                return m_MINIMUM_DATA_COMPONENTS;
            }
        }

        public static int MAXIMUM_REPVERSION
        {
            get
            {
                return m_MAXIMUM_REPVERSION;
            }
        }

        public static string WebServicesURL
        {
            get
            {
                return webService.Url;
            }
            set
            {
                webService.Url = value;
            }
        }
        #endregion

        #region Offline Data
        #region Filling Offline Data
        private static void FillOfflineAccessLevels(DbCommand command)
        {
            string query = @"SELECT AccessID, AccessName FROM AccessLevels";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);

            command.CommandText = @"INSERT INTO AccessLevels(AccessID, AccessName) 
                VALUES(@AccessID, @AccessName)";
            foreach (DataRow row in dataTable.Rows)
            {
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@AccessID";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@AccessName";
                param.Value = row[1];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }

        private static void FillOfflineRegions(DbCommand command)
        {
            string query = @"SELECT RegionNo, RegionName FROM Region";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO Region(RegionNo, RegionName) VALUES(@RegionNo, @RegionName)";
            //transaction = command.Connection.BeginTransaction();
            //command.Transaction = transaction;
            foreach (DataRow row in dataTable.Rows)
            {
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@RegionNo";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@RegionName";
                param.Value = row[1];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }

        private static void FillOfflineDistricts(DbCommand command)
        {
            string query = @"SELECT DistrictNo, District, RegionNo FROM District";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO District(DistrictNo, District, RegionNo) 
                VALUES(@DistrictNo, @District, @RegionNo)";
            //transaction = command.Connection.BeginTransaction();
            //command.Transaction = transaction;
            foreach (DataRow row in dataTable.Rows)
            {
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@DistrictNo";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@District";
                param.Value = row[1];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@RegionNo";
                param.Value = row[2];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }

        private static void FillOfflineFacilities(DbCommand command)
        {
            string query = @"SELECT FacCode, FacName, FacShortName, Region, District, PMTCT, LD,
                PMTCTYear, PMTCTPeriod, LDYear, LDPeriod, Description, Address,
                PrincipalContact, Status, Remarks, ANCStartDate, LDStartDate, HEIDStartDate,
                ANC, HEID, PMTCTStartDate, Prophylaxis, ProphylaxisStartDate, ActiveDate,
                InactiveDate FROM Facilities";//20040132 04080119
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO Facilities(FacCode, FacName, FacShortName, 
                Region, District, PMTCT, LD, PMTCTYear, PMTCTPeriod, LDYear, LDPeriod, 
                Description, Address, PrincipalContact, Status, Remarks, ANCStartDate, 
                LDStartDate, HEIDStartDate, ANC, HEID, PMTCTStartDate, Prophylaxis, 
                ProphylaxisStartDate, ActiveDate, InactiveDate) 
                VALUES(@FacCode, @FacName, @FacShortName, @Region, @District, @PMTCT, @LD,
                @PMTCTYear, @PMTCTPeriod, @LDYear, @LDPeriod, @Description, @Address,
                @PrincipalContact, @Status, @Remarks, @ANCStartDate, @LDStartDate, @HEIDStartDate,
                @ANC, @HEID, @PMTCTStartDate, @Prophylaxis, @ProphylaxisStartDate, @ActiveDate,
                @InactiveDate)";
            int i = 0;
            foreach (DataRow row in dataTable.Rows)
            {
                i++;
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@FacCode";
                param.Value = row[0];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@FacName";
                param.Value = row[1];
                param.DbType = DbType.String;
                param.Size = 255;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@FacShortName";
                param.Value = row[2];
                param.DbType = DbType.String;
                param.Size = 255;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Region";
                param.Value = row[3];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@District";
                param.Value = row[4];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@PMTCT";
                param.Value = row[5];
                param.DbType = DbType.Boolean;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@LD";
                param.Value = row[6];
                param.DbType = DbType.Boolean;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@PMTCTYear";
                param.Value = row[7];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@PMTCTPeriod";
                param.DbType = DbType.Int32;
                param.Value = row[8];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@LDYear";
                param.DbType = DbType.Int32;
                param.Value = row[9];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@LDPeriod";
                param.DbType = DbType.Int32;
                param.Value = row[10];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Description";
                param.DbType = DbType.Int32;
                param.Value = row[11];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Address";
                param.DbType = DbType.Int32;
                param.Value = row[12];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@PrincipalContact";
                param.DbType = DbType.Int32;
                param.Value = row[13];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Status";
                param.Value = row[14];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Remarks";
                param.DbType = DbType.Int32;
                param.Value = row[15];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@ANCStartDate";
                param.Value = row[16];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@LDStartDate";
                param.Value = row[17];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@HEIDStartDate";
                param.Value = row[18];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param); ;

                param = command.CreateParameter();
                param.ParameterName = "@ANC";
                param.Value = row[19];
                param.DbType = DbType.Boolean;
                command.Parameters.Add(param); ;

                param = command.CreateParameter();
                param.ParameterName = "@HEID";
                param.Value = row[20];
                param.DbType = DbType.Boolean;
                command.Parameters.Add(param); ;

                param = command.CreateParameter();
                param.ParameterName = "@PMTCTStartDate";
                param.Value = row[21];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param); ;

                param = command.CreateParameter();
                param.ParameterName = "@Prophylaxis";
                param.Value = row[22];
                param.DbType = DbType.Boolean;
                command.Parameters.Add(param); 

                param = command.CreateParameter();
                param.ParameterName = "@ProphylaxisStartDate";
                param.Value = row[23];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param); 

                param = command.CreateParameter();
                param.ParameterName = "@ActiveDate";
                param.Value = row[24];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param); 

                param = command.CreateParameter();
                param.ParameterName = "@InactiveDate";
                param.Value = row[25];
                param.DbType = DbType.DateTime;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }

        private static void FillOfflineReport(DbCommand command)
        {
            string query = @"SELECT RepID, ReportName, RepVersion, RepTemplate FROM Report";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO Report(RepID, ReportName, RepVersion, RepTemplate) 
                VALUES(@RepID, @ReportName, @RepVersion, @RepTemplate)";
            //transaction = command.Connection.BeginTransaction();
            //command.Transaction = transaction;
            foreach (DataRow row in dataTable.Rows)
            {
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@RepID";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@ReportName";
                param.Value = row[1];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@RepVersion";
                param.Value = row[2];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@RepTemplate";
                param.Value = row[3];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }

        private static void FillOfflineReportDataLocations(DbCommand command)
        {
            string query = @"SELECT MeasureNo, RepID, DataDescription, DataPosition, DataType,
                ShortCode FROM ReportDataLocations";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO ReportDataLocations(MeasureNo, RepID, 
                DataDescription, DataPosition, DataType, ShortCode) 
                VALUES(@MeasureNo, @RepID, @DataDescription, @DataPosition, @DataType,
                @ShortCode)";
            //transaction = command.Connection.BeginTransaction();
            //command.Transaction = transaction;
            foreach (DataRow row in dataTable.Rows)
            {
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@MeasureNo";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@RepID";
                param.Value = row[1];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@DataDescription";
                param.Value = row[2];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@DataPosition";
                param.Value = row[3];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@DataType";
                param.Value = row[4];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@ShortCode";
                param.Value = row[5];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }

        private static void FillOfflineReportData(DbCommand command)
        {
            string query = @"SELECT TOP(20000) SID, ReceivedSMSNo, RepID, DataPosition, Data FROM ReportData";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO ReportData(SID, ReceivedSMSNo, 
                RepID, DataPosition, Data) VALUES(@SID, @ReceivedSMSNo, @RepID, 
                @DataPosition, @Data)";
            //            string SELECT = @"SELECT * FROM ReportData WHERE SID=0";
            //            string INSERT = @"INSERT INTO ReportData(SID, ReceivedSMSNo, 
            //                RepID, DataPosition, Data) VALUES(@SID, @ReceivedSMSNo, @RepID, 
            //                @DataPosition, @Data)";

            //            OleDbConnection connection = (OleDbConnection) command.Connection;
            //            OleDbDataAdapter adapter = new OleDbDataAdapter(SELECT, connection);
            //            dataTable = new DataTable();
            //            adapter.Fill(dataTable);

            //            for (int x = 0; x < data.Rows.Count; x++)
            //            {
            //                DataRow row = dataTable.NewRow();
            //                row["SID"] = data.Rows[x]["SID"];
            //                row["ReceivedSMSNo"] = data.Rows[x]["ReceivedSMSNo"];
            //                row["RepID"] = data.Rows[x]["RepID"];
            //                row["DataPosition"] = data.Rows[x]["DataPosition"];
            //                row["Data"] = data.Rows[x]["Data"];
            //                dataTable.Rows.Add(row);
            //            }

            //            adapter.InsertCommand = new OleDbCommand(INSERT);
            //            adapter.InsertCommand.Parameters.Add("@SID", OleDbType.Integer, 8, "SID");
            //            adapter.InsertCommand.Parameters.Add("@ReceivedSMSNo", OleDbType.Integer, 8, "ReceivedSMSNo");
            //            adapter.InsertCommand.Parameters.Add("@RepID", OleDbType.Integer, 8, "RepID");
            //            adapter.InsertCommand.Parameters.Add("@DataPosition", OleDbType.Integer, 8, "DataPosition");
            //            adapter.InsertCommand.Parameters.Add("@Data", OleDbType.VarChar, 255, "Data");
            //            adapter.InsertCommand.Connection = connection;
            //            adapter.Update(dataTable);
            //            adapter.InsertCommand.Connection.Close();

            //transaction = command.Connection.BeginTransaction();
            //command.Transaction = transaction;
            //i = 0;
            foreach (DataRow row in dataTable.Rows)
            {
                //i++;
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@SID";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@ReceivedSMSNo";
                param.Value = row[1];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@RepID";
                param.Value = row[2];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@DataPosition";
                param.Value = row[3];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Data";
                param.Value = row[4];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();

                //if ((i % 1000) == 0)
                //{
                //    transaction.Commit();
                //    transaction = command.Connection.BeginTransaction();
                //    command.Transaction = transaction;
                //}
            }
        }

        private static void FillOfflinePresetCharts(DbCommand command)
        {
            string query = @"SELECT ChartID, ChartName FROM PresetCharts";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO PresetCharts(ChartID, ChartName) VALUES(@ChartID, @ChartName)";
            foreach (DataRow row in dataTable.Rows)
            {
                //i++;
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@ChartID";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@ChartName";
                param.Value = row[1];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();

                //if ((i % 1000) == 0)
                //{
                //    transaction.Commit();
                //    transaction = command.Connection.BeginTransaction();
                //    command.Transaction = transaction;
                //}
            }
        }

        private static void FillOfflinePresetChartsIndicators(DbCommand command)
        {
            string query = @"SELECT IndicatorID, ChartID, CompositeIndicator, IndicatorName, 
                IndicatorDefinition FROM PresetChartsIndicators";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO PresetChartsIndicators(IndicatorID, ChartID, 
                CompositeIndicator, IndicatorName, IndicatorDefinition) 
                VALUES(@IndicatorID, @ChartID, @CompositeIndicator, @IndicatorName, 
                @IndicatorDefinition)";
            foreach (DataRow row in dataTable.Rows)
            {
                //i++;
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@IndicatorID";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@ChartID";
                param.Value = row[1];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@CompositeIndicator";
                param.Value = row[2];
                param.DbType = DbType.Boolean;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@IndicatorName";
                param.Value = row[3];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@IndicatorDefinition";
                param.Value = row[4];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();

                //if ((i % 1000) == 0)
                //{
                //    transaction.Commit();
                //    transaction = command.Connection.BeginTransaction();
                //    command.Transaction = transaction;
                //}
            }
        }

        private static void FillOfflineUsers(DbCommand command)
        {
            string query = @"SELECT ID, UserID, UserPass, Username, FirstName, LastName, Password, EmailAddress,
                AccessLevelID, AccessLevelValue FROM Users";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = @"INSERT INTO Users(ID, UserID, UserPass, Username, FirstName, LastName, 
                Password, EmailAddress, AccessLevelID, AccessLevelValue) VALUES(@ID, @UserID, @UserPass,
                @Username, @FirstName, @LastName, @Password, @EmailAddress, @AccessLevelID, @AccessLevelValue)";
            foreach (DataRow row in dataTable.Rows)
            {
                //i++;
                command.Parameters.Clear();
                DbParameter param = command.CreateParameter();
                param.ParameterName = "@ID";
                param.Value = row[0];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@UserID";
                param.Value = row[1];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@UserPass";
                param.Value = row[2];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Username";
                param.Value = row[3];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@FirstName";
                param.Value = row[4];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@LastName";
                param.Value = row[5];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@Password";
                param.Value = row[6];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@EmailAddress";
                param.Value = row[7];
                param.DbType = DbType.String;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@AccessLevelID";
                param.Value = row[8];
                param.DbType = DbType.Int32;
                command.Parameters.Add(param);

                param = command.CreateParameter();
                param.ParameterName = "@AccessLevelValue";
                param.Value = row[9];
                param.DbType = DbType.String;
                command.Parameters.Add(param);
                command.ExecuteNonQuery();

                //if ((i % 1000) == 0)
                //{
                //    transaction.Commit();
                //    transaction = command.Connection.BeginTransaction();
                //    command.Transaction = transaction;
                //}
            }
        }

        private static void FillOfflineYears(DbCommand command)
        {
            string query = @"SELECT DISTINCT Year FROM ReceivedSMS WHERE 
                (Year BETWEEN 1990 AND 2050) ORDER BY Year";
            DataTable dataTable = GenericDataAccess.RunSelectQuery(query);
            command.CommandText = "INSERT INTO ReportYears(ReportYear) VALUES(@ReportYear)";
            DbParameter param = null;
            foreach (DataRow row in dataTable.Rows)
            {
                command.Parameters.Clear();
                param = command.CreateParameter();
                param.ParameterName = "@ReportYear";
                param.DbType = DbType.Int32;
                param.Value = row[0];
                command.Parameters.Add(param);
                command.ExecuteNonQuery();
            }
        }
        #endregion

        public static void GetOfflineDBPath()
        {
            try
            {
                string currentStatus = Utilities.GetSetting(SETTING_CACHEDB_STATUS);
                if (currentStatus == CACHEDB_STATUS_CREATING) return;   // There is a thread working on this

                string templatePath = Utilities.GetSetting(SETTING_TEMPLATE_CACHEDB_NAME);
                string outputFile = String.Format("{0}.mdb", Guid.NewGuid().ToString());
                string newFile = outputFile;
                string path = String.Empty;
                if (templatePath.Contains(@"\"))
                {
                    int length = templatePath.LastIndexOf(@"\") + 1;
                    path = templatePath.Substring(0, length);
                }
                else path = "";
                outputFile = String.Format("{0}{1}", path, outputFile);
                File.Copy(templatePath, outputFile);

                string oldFile = "Cache.mdb";
                string connectionString = AppConfiguration.CacheDBConnectionString.Replace(oldFile, newFile);
                DbCommand command = GenericDataAccess.CreateCommand(
                    AppConfiguration.CacheDBProviderName, connectionString);
                command.Connection.Open();

                Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_CREATING);
                try
                {
                    DataSet offlineDataSet = new DataSet();
                    command.CommandText = "SELECT * FROM ImportTables";
                    DataTable tables = GenericDataAccess.ExecuteSelectCommand(command, false);
                    
                    DbCommand sqlCommand = GenericDataAccess.CreateCommand();
                    sqlCommand.CommandType = CommandType.Text;
                    foreach (DataRow table in tables.Rows)
                    {
                        string tableName = table["TableName"].ToString();
                        string query = String.Format("SELECT * FROM {0}", tableName);
                        sqlCommand.CommandText = query;
                        DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(sqlCommand, false);
                        dataTable.TableName = tableName;
                        offlineDataSet.Tables.Add(dataTable);
                    }

                    offlineDataSet.WriteXml(@"C:\IQSMS\Sample.xml", XmlWriteMode.WriteSchema);
                    

                    // Setting cache creation date
                    /*command.CommandText = @"INSERT INTO SysSettings(SettingName, SettingValue) 
                    VALUES(@SettingName, @SettingValue)";
                    command.Parameters.Clear();
                    DbParameter param = command.CreateParameter();
                    param.ParameterName = "@SettingName";
                    param.DbType = DbType.String;
                    param.Value = SETTING_CACHEDB_CREATE_DATE;
                    command.Parameters.Add(param);

                    param = command.CreateParameter();
                    param.ParameterName = "@SettingValue";
                    param.DbType = DbType.String;
                    DateTime now = DateTime.Now;
                    param.Value = String.Format("{0}-{1}-{2}", now.Year, now.Month, now.Day);
                    command.Parameters.Add(param);
                    command.ExecuteNonQuery();*/
                }
                catch (Exception ex)
                {
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                    File.Delete(outputFile);
                    Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_ERROR);
                    Utilities.LogError(ex, null);
                    return;
                }
                finally
                {
                    if (command.Connection.State != ConnectionState.Closed) command.Connection.Close();
                }

                // Now move the file to cache folder
                string newFilename = outputFile.Replace("App_Data", "Cache");
                File.Move(outputFile, newFilename);

                FileInfo inputFile = new FileInfo(newFilename);
                string compressedFile = DataTransformation.Compress(inputFile);
                File.Delete(newFilename);
                FileInfo outFile = new FileInfo(compressedFile);
                Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_READY);
            }
            catch (Exception except)
            {
                Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_ERROR);
                Utilities.LogError(except, null);
            }
        }

        private const string RECEIVED_SMS_TABLE_NAME = "ReceivedSMS";
        private const string REPORT_DATA_TABLE_NAME = "ReportData";
        public static void GetOfflineDBPath2(DateTime cutOffDate, string schemaLocation)
        {
            try
            {
                string currentStatus = Utilities.GetSetting(SETTING_CACHEDB_STATUS);
                if (currentStatus == CACHEDB_STATUS_CREATING) return;   // There is a thread working on this

                string templatePath = Utilities.GetSetting(SETTING_TEMPLATE_CACHEDB_NAME);
                string outputFile = templatePath.Replace(".mdb", ".xml");
                Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_CREATING);

                DataSet offlineDataSet = new DataSet();
                DbCommand sqlCommand = GenericDataAccess.CreateCommand();
                sqlCommand.CommandType = CommandType.Text;
                try
                {                    
                    sqlCommand.CommandText = "SELECT [TableName] FROM ImportTables";
                    DataTable tables = GenericDataAccess.ExecuteSelectCommand(sqlCommand, false);
                    foreach (DataRow table in tables.Rows)
                    {
                        DataTable dataTable = null;
                        string tableName = table["TableName"].ToString();
                        string query = String.Format("SELECT * FROM {0}", tableName);
                        if ((tableName == RECEIVED_SMS_TABLE_NAME) || (tableName == REPORT_DATA_TABLE_NAME))
                        {
                            // Select data based on cut-off date
                            if (tableName == RECEIVED_SMS_TABLE_NAME)
                            {
                                query = "SELECT * FROM ReceivedSMS WHERE ReportDate >= @ReportDate";
                                sqlCommand.CommandText = query;                               
                            }

                            if (tableName == REPORT_DATA_TABLE_NAME)
                            {
                                query = @"SELECT ReportData.SID, ReportData.ReceivedSMSNo, 
                                    ReportData.RepID, ReportData.DataPosition, ReportData.Data
                                    FROM ReportData INNER JOIN
                                    ReceivedSMS ON ReportData.ReceivedSMSNo = ReceivedSMS.ReceivedSMSNo
                                    WHERE (ReceivedSMS.ReportDate >= @ReportDate)";
                                sqlCommand.CommandText = query;
                            }

                            DbParameter param = sqlCommand.CreateParameter();
                            param.ParameterName = "@ReportDate";
                            param.DbType = DbType.DateTime;
                            param.Value = cutOffDate;
                            sqlCommand.Parameters.Add(param);
                            dataTable = GenericDataAccess.ExecuteSelectCommand(sqlCommand, false);
                            sqlCommand.Parameters.Clear();
                        }
                        else
                        {
                            sqlCommand.CommandText = query;
                            dataTable = GenericDataAccess.ExecuteSelectCommand(sqlCommand, false);
                        }
                        dataTable.TableName = tableName;

                        // This is special treatment of ImportTables to include the database schema
                        // for all tables.
                        if (tableName == "ImportTables")
                        {
                            foreach (DataRow r in dataTable.Rows)
                            {
                                int creationOrder = int.Parse(r["CreationOrder"].ToString());
                                if (creationOrder == 0)
                                {
                                    // Get the database schema from a file.
                                    var schema = File.ReadAllText(schemaLocation);
                                    r["CreateSQL"] = schema;
                                    break;
                                }
                            }
                        }
                        offlineDataSet.Tables.Add(dataTable);
                    }

                    offlineDataSet.WriteXml(outputFile, XmlWriteMode.WriteSchema);
                }
                catch (Exception ex)
                {
                    if (sqlCommand.Connection.State != ConnectionState.Closed) sqlCommand.Connection.Close();
                    File.Delete(outputFile);
                    Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_ERROR);
                    Utilities.LogError(ex, null);
                    return;
                }
                finally
                {
                    if (sqlCommand.Connection.State != ConnectionState.Closed) sqlCommand.Connection.Close();
                    offlineDataSet.Dispose();
                }

                // Now move the file to cache folder
                string newFilename = outputFile.Replace("App_Data", "Cache");
                File.Move(outputFile, newFilename);

                FileInfo inputFile = new FileInfo(newFilename);
                string compressedFile = DataTransformation.Compress(inputFile);
                File.Delete(newFilename);
                FileInfo outFile = new FileInfo(compressedFile);
                Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_READY);
            }
            catch (Exception except)
            {
                Utilities.SetSetting(SETTING_CACHEDB_STATUS, CACHEDB_STATUS_ERROR);
                Utilities.LogError(except, null);
            }
        }

        public static DateTime? GetOfflineDataDate()
        {
            // Determing the last creation of offline data
            DbCommand command = GenericDataAccess.CreateCacheDBCommand();
            command.CommandText = @"SELECT SettingValue FROM SysSettings WHERE SettingName=@SettingName";
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@SettingName";
            param.DbType = DbType.String;
            param.Value = Utilities.SETTING_CACHEDB_CREATE_DATE;
            command.Parameters.Add(param);
            string settingValue = null;

            SqlCommand sqlCommand = command as SqlCommand;
            if (sqlCommand != null)
            {
                try
                {
                    SqlConnection connection = sqlCommand.Connection;
                    if (connection.State != ConnectionState.Open) connection.Open();

                    object value = sqlCommand.ExecuteScalar();
                    connection.Close();
                    sqlCommand.Dispose();

                    if (value == null) settingValue = null;
                    else settingValue = value.ToString();
                    if (string.IsNullOrWhiteSpace(settingValue)) return null;
                    else
                    {
                        DateTime creationDate;
                        bool converted = DateTime.TryParse(settingValue, out creationDate);
                        if (!converted) return null;
                        else return creationDate;
                    }
                }
                catch
                {
                    return null;
                }
            }
            else return null;
        }

        public static DateTime? GetOfflineDataCutOffPoint()
        {
            // Determing the last creation of offline data
            DbCommand command = GenericDataAccess.CreateCacheDBCommand();
            command.CommandText = @"SELECT SettingValue FROM SysSettings WHERE SettingName=@SettingName";
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@SettingName";
            param.DbType = DbType.String;
            param.Value = Utilities.SETTING_CACHEDB_CUT_OFF_POINT;
            command.Parameters.Add(param);
            string settingValue = null;

            bool logMail = AppConfiguration.EnableErrorLogMail;
            try
            {
                AppConfiguration.EnableErrorLogMail = false;    // Temporarily disabling error logging
                settingValue = GenericDataAccess.ExecuteScalar(command);
                if (String.IsNullOrEmpty(settingValue)) return null;
                else
                {
                    try
                    {
                        DateTime cutOffPoint = DateTime.Parse(settingValue);
                        return cutOffPoint;
                    }
                    catch
                    {
                        return null;
                    }
                }
            }
            catch
            {
                return null;
            }
            finally
            {
                AppConfiguration.EnableErrorLogMail = logMail;  // Restore error logging settings
            }
        }
        #endregion

        #region Modem Identification
        public static string GetModemServiceOperator(string mobileNetworkCode)
        {
            if (mobileNetworkCode.Length < 5) return "NOT KNOWN/AVAILABLE";
            string mcc = mobileNetworkCode.Substring(0, 3);
            string mnc = mobileNetworkCode.Substring(3);

            DbCommand command = GenericDataAccess.CreateCommand();
            command.CommandText = @"SELECT Brand, Operator FROM MobilePhoneOperators 
                WHERE (MCC = @MCC) AND (MNC = @MNC)";
            DbParameter param = command.CreateParameter();
            param.ParameterName = "@MCC";
            param.DbType = DbType.String;
            param.Value = mcc;
            command.Parameters.Add(param);

            param = command.CreateParameter();
            param.ParameterName = "@MNC";
            param.DbType = DbType.String;
            param.Value = mnc;
            command.Parameters.Add(param);

            DataTable dataTable = GenericDataAccess.ExecuteSelectCommand(command);
            if (dataTable.Rows.Count > 0)
            {
                DataRow row = dataTable.Rows[0];
                string brand = row["Brand"].ToString();
                string carrier = row["Operator"].ToString();
                if (String.IsNullOrEmpty(brand))
                {
                    if (String.IsNullOrEmpty(carrier)) return "NOT KNOWN/AVAILABLE";
                    else return carrier;
                }
                else return brand;
            }
            else
            {
                return "NOT KNOWN/AVAILABLE";
            }
        }
        #endregion

        #region Database Backup
        public static string BackupSQLDatabase(string connectionString, string databaseName, string outputFile)
        {
            SqlConnection connection = new SqlConnection(connectionString);
            connection.Open();
            string query = String.Format("BACKUP DATABASE [{0}] TO DISK = '{1}'", databaseName, outputFile);
            SqlCommand command = connection.CreateCommand();
            command.CommandText = query;
            command.ExecuteNonQuery();
            connection.Close();
            return outputFile;
        }
        #endregion

        #region Excel File Exporting
        public static void WriteDataTableToExcelSheet(Excel.Worksheet excelWorksheet, 
            DataTable dataTable, int rowOffset, int columnOffset, bool includeHeader)
        {
            if (rowOffset < 1) rowOffset = 1;
            if (columnOffset < 1) columnOffset = 1;
            Type stringType = Type.GetType("System.String");

            if (includeHeader)
            {
                int columnIndex = columnOffset;
                foreach (DataColumn column in dataTable.Columns)
                {
                    string name = column.ColumnName;
                    Excel.Range cell = (Excel.Range)excelWorksheet.Cells[rowOffset, columnIndex];
                    cell.Value = name;
                    cell.Font.Bold = true;
                    
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(cell);
                    columnIndex++;
                }
                rowOffset++;
            }
            for (int r = 0; r < dataTable.Rows.Count; r++)
            {
                DataRow row = dataTable.Rows[r];
                int rowIndex = r + rowOffset;
                for (int c = 0; c < dataTable.Columns.Count; c++)
                {
                    DataColumn column = dataTable.Columns[c];
                    object cell = row[c];
                    int columnIndex = c + columnOffset;
                    
                    Excel.Range excelCell = (Excel.Range)excelWorksheet.Cells[rowIndex, columnIndex];
                    if (column.DataType == stringType) excelCell.NumberFormat = "@";
                    excelCell.Value = cell.ToString();
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(excelCell);
                }
            }
        }
        #endregion
    }
}
